Suppose I have a large class with a lot of functionality and a relatively large interface. Particularly, there are many constructors for convenient instantiation. From this class, several classes could be derived with some slightly extended interface and/or customized virtual functions.
The problem: I will have to copy all the constructors into the derived classes which would mean a lot of code duplication. Even worse: The constructors slightly depend on the derived class, which I would solve by a virtual call, but this does not work in a constructor.
What's a good approach to tackle this problem?
EDIT: I know that I can delegate constructors Derived(arguments) : Base(arguments) {} but I'd still need to copy parts of the constructor which I try to avoid.
Use using declarations to make the constructors of the base class aviable on the derived one:
class Base
{
public:
Base( int , int , int );
};
class Derived : public Base
{
public:
using Base::Base; //Automatically adds all the base constructors
};
EDIT: Here is a running example.
I do not know exactly if it works for your problem, but you might think about making some kind of 'initialization' object where you handle the properties of the object you want to create. This will have a lot of constructors.
Then you pass this object to the 'real' class where the properties are used to create the actual object.
If C++ 11 extensions can be used, then the other answer that recommends using is a perfect answer.
If not, then the only way is:
class x: public y
{
// modified constructors:
x (int a) : y (1, 2, a + 3) { your code if any; }
x (int a, int b) : y (b, a) { your code if any; }
// delegated constructors: alas, repeated for all constructors of y
x (int c, float d) : y (c, d) { /* no code*/ }
x (float e, int f) : y (e, f) { /* no code*/ }
}
The latter part is not really code duplication because you only duplicate interface but no code.
Do the initializations applicable in respective classes. For example, say A is superclass and B is a subclass, so you may use,
B::B(...arguments...): A(...arguments that you would like to pass to superclass constructor)
{
}
Related
Consider we have an library that contains a base class, like below,
class Base{
protected:
int a;
public:
Base(int a) : a(a) {}
};
Then, I want to extend it in a new library by adding a new function, like below
class Derived : public Base{
public:
bool is_greater(Derived &y) { return a > y.a; }
};
So that, we can compare their member values using member function is_greater, as
int main(){
Base b1, b2 = // get from the old library's output
Derived d1 = b1, d2 = b2 // convert from base class to derived class
d1.is_greater(d2);
}
So, what's the best solution for this kind of conversion?, performance is the most important point I am concerned about.
Just like any other conversion. You can use a converting constructor:
explicit Derived(const Base& base): Base(base) {}
Conversion operator isn't a practical option in this case since the base doesn't know about the derived type.
Extending a class to add functionality is only viable when either
The class is designed to be extended that way, polymorphic with appropriate APIs, or
You use your extended class everywhere, not the base class.
... otherwise, there is no way to avoid copies or dangerous casts with potential undefined behavior.
Regardless, I'm of the opinion that equating "extension" to "inheritance" is a code smell made popular by abuse of OOP. C++ has free functions. It's un-intrusive and allows you to work with the type and objects you really mean to work with. Furthermore, that protected member is still accessible if you are savvy:
bool is_greater(Base const& l, Base const& r) {
struct fetch : Base { using Base::a; };
return l.*(&fetch::a) > r.*(&fetch::a);
}
We define a local class that inherits from Base, yes. But we don't do it to mess around with objects of the wrong type. All it does is make the member accessible to us. Then we simply use pointer-to-member syntax to access that member on our Base objects in a well-defined manner.
Why did the creator of C++ decide to use constructor initializer list to initialize base classes? Why didn't he instead choose to use syntax like the second comment line in the following code?
class A{
public:
A() { }
};
class B : A{
public:
B() : A() { } // Why decide to use this one, using constructor initializer, to initialize base class?
B() { A(); } // Why not choose this one? It's easy for me to understand if it was possible.
};
int main(int argc, char *argv[]){
/* do nothing */
}
The advantage of using an initializer list is, that you have a completely initialized object in the body of the constructor.
class A {
public:
A(const int val) : val(val) { }
private:
const int val;
};
class B : A{
public:
B() : A(123) {
// here A and B are already initialized
}
};
So you have a guarantee that all members, even those of the parent, are not in an undefined state.
Edit
In the example of the question it is not necessary to call the base class in the initializer list, this is done automatically. So I slightly modified the example.
I can see a few possible alternatives to the current C++ rule that base classes and data members of a class type are initialised in the mem-initialiser list of the class type's constructor(s). They all come with their set of issues, which I will discuss below.
But first, note that you cannot simply write a derived constructor like this:
struct Derived : Base
{
Derived()
{
Base(42);
}
};
and expect the line Base(42); to call the base class constructor. Everywhere else in C++, such a statement creates a temporary object of type Base initialised with 42. Changing its meaning inside a constructor (or just inside its first line?) would be a syntax nightmare.
Which means that new syntax would need to be introduced for this. In the rest of this answer, I will use a hypothetical construct __super<Base> for this.
Now on to discuss possible approaches which would be closer to your desired syntax, and present their problems.
Variant A
Base classes are initialised in the constructor body, while data members are still initialised in the mem-initialiser list. (This follows the letter of your question the closest).
The would have the immediate problem of stuff executing in different order than it's written. For very good reasons, the rule in C++ is that base class subobjects are initialised before any data members of the derived class. Imagine this use case:
struct Base
{
int m;
Base(int a) : m(a) {}
};
struct Derived
{
int x;
Derived() :
x(42)
{
__super<Base>(x);
}
};
Written like this, you could easily assume x would be initialised first and then Base would be initialised with 42. However, that would not be the case and instead reading x would be undefined.
Variant B
Mem-initialiser lists are removed altogether, base classes are initialised using __super, and data members are simply assigned in the constructor body (pretty much the way Java does it).
This cannot work in C++ because initialisation and assignment are fundamentally different concepts. There are types where the two operations do vastly different things (e.g. references), and types which are not assignable at all (e.g. std::mutex).
How would this approach deal with a situtation like this?
struct Base
{
int m;
Base(int a) : { m = a; }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x); // This one's OK
r = *pd; // PROBLEM
}
};
Consider the line marked // PROBLEM. Either it means what it normally does in C++ (in which case it assigns a double into a "random place" which the uninitialised reference r references), or we change its semantics in constructors (or just in initial parts of a constructor?) to do initialisation instead of assignment. The former gives us a buggy program while the latter introduces totally chaotic syntax and unreadable code.
Variant C
Like B above, but introduce special syntax for initialising a data member in the constructor body (like we did with __super). Something like __init_mem:
struct Base
{
int m;
Base(int a) : { __init_mem(m, a); }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x);
__init_mem(r, *pd);
}
};
Now, the question is, what have we achieved? Previously, we had the mem-initialiser list, a special syntax to initialise bases and members. It had the advantage that it made clear these things happen first, before the constructor body starts. Now, we have a special syntax to initialise bases and members, and we need to force the programmer to put it at the start of the constructor.
Note that Java can get away with not having a mem-initialiser list for several reasons which don't apply to C++:
The syntax for creating an object is always new Type(args) in Java, whereas Type(args) can be used in C++ to construct objects by value.
Java only uses pointers, where initialisation and assignment are equivalent. For many C++ types, there operations are distinct.
Java classes can only have one base class, so using just super is enough. C++ would need to differentiate which base class you're referring to.
B() : A() { }
This will initialize the base class in user defined way.
B() { A(); }
This will NOT initialize the base class in user defined way.
This will create an object inside of constructor i.e B(){}
I think first initialization has better readability compared to the second and you can also deduce class hierarchy.
I have a classic diamond problem like this in C++
A
/ \
B C
\ /
D
I know this would normally be solved by making B and C inherit virtually from A.
But my issue is that classes A and B come from a third party library I can't edit and B's inheritance from A is not marked virtual.
Is there a way to solve this?
Thanks for the help ;-)
An simple way to solve this problem is to introduce an Adapter class. This way, the hierarchy becomes
A
/
B AdapterC
\ /
D
And the code of AdapterC would look like
class AdapterC
{
public:
explicit AdapterC(C c) : c(std::move(c)) {}
operator C& () { return c; } //Maybe this should be explicit too...
/** Interface of C that you want to expose to D, e.g.
int doSomething(double d) { return c.doSomething(d); }
**/
private:
C c;
};
As the saying goes, "All problems in computer science can be solved by another level of indirection, except of course for the problem of too many indirections". Of course, it might be a lot of work to write and maintain this Adapter. Hence, I think people that comment your question are probably right and that you should revisit your design.
Key design issue
If you can't change the inheritance of A in your library to virtual, there is no way to make a diamond with a single A element a the top. The standard explicitly allows for mixing virtual and non-virtual inheritance of the same base class:
10.1/6: for an object c of class type C, a single subobject of type V is shared by every base subobject of c that has a virtual base
class of type V. (...).
10.1/7: A class can have both virtual and non-virtual base classes of a given type.
Example:
namespace mylib { // namesape just to higlight the boundaries of the library
struct Person { // A
static int counter;
int id;
Person() : id(++counter) {}
void whoami() { cout << "I'm "<<id<<endl; }
}; //A
struct Friend: Person {}; //B -> A
int Person::counter=0;
}
struct Employee : virtual mylib::Person {}; // C->A
struct Colleague : Employee, mylib::Friend {}; // D->(B,c)
...
mylib::Friend p1; // ok !
p1.whoami();
Employee p2; // ok !
p2.whoami();
Colleague p3; // Attention: No diamond !
//p3.whoami(); // ouch !! not allowed: no diamond so for which base
// object has the function to be called ?
p3.Employee::whoami(); // first occurrence of A
p3.mylib::Friend::whoami(); // second second occurrence of A
Online demo
Alternative design
As you have no way to intervene in your external library you have to organize things differently. But however you'll do it, it will be sweat and tears.
You could define C (Employee in my example) by using composition of A (Person in my example). The A subobject would either be created or in special cases taken over from another object. You'd need to undertake the effort to replicate A's interface, forwarding the calls to an A subobject.
The general idea would look like:
class Employee {
mylib::Person *a;
bool owna;
protected:
Employee (mylib::Person& x) : a(&x), owna(false) { } // use existing A
public:
Employee () : a(new mylib::Person), owna(true) { } // create A subobject
~Employee () { if (owna) delete a; }
void whoami() { a->whoami(); } // A - fowarding
};
If you do this, you could then define D with multiple inheritance, with a trick in the constructor:
struct Colleague : mylib::Friend, Employee {
Colleague () : mylib::Friend(), Employee(*static_cast<Person*>(this)) {};
using Friend::whoami;
};
The only issue would then the ambiguity of the member functions of A interface (that have been provided in C as explained above). You therefore have to tell with a using clause that for A, you go via B and not via C.
In final, you could use this:
Employee p2;
p2.whoami();
Colleague p3; // Artifical diamond !
p3.whoami(); // YES !!
p3.Employee::whoami(); // first occurence of A
p3.mylib::Friend::whoami(); // second second occurence of A
// all whoami refer to the same A !!!
It works nicely: Online demo
Conclusion
So yes, it's possible to solve this, but it's very tricky. As I said: it will be sweat and tears.
For instance, you have no problem to convert a Colleague to a Person. But for Employee, you'd need to provide conversion operators. You have to implement the rule of 3/5 in Employee And you have to take care of everything that could go wrong (failed allocation, etc...). It will not be a piece of cake.
So it's really worth to reconsider your design, as Lightness Races in Orbit suggested in the comments :-)
Objective-C category feature allows programmer to add new method which was not defined in original class definition.
Can I archive similar functionality (language construct or some technique) on C++?
Major concern is consistent method calling syntax (. or -> operator).
Let's consider the following class to be extended:
struct A {
int x, y;
A(int x, int y) : x(x), y(y) {}
};
You can inherit from this class or write a wrapper class which contains an instance of this class. In most cases, inheritance is the way to go, as a wrapper class isn't an A but it wraps (contains) an A.
With C++11 move semantics, promoting an instance A to a subclass B (inheriting A) will be efficient and doesn't require to copy the instance A:
class B : public A {
public:
B (A &&a) : A(a), someOtherMember(a.x + a.y) {}
// added public stuff:
int someOtherFunction() const { return someOtherMember; }
private:
// added private stuff:
int someOtherMember;
};
Full code with example: http://ideone.com/mZLLEu
Of course the function I added is a bit silly (and the member even more, since it doesn't respect further changes of the original members x and y), but you should get an idea of what I want to demonstrate.
Note the constructor B (A &&a) which is something I call "promote constructor" (this is not a standard term). Normally, B (B &&b) is a move constructor, which moves the contents of the provided B instance into a new B about to be constructed. I use the move semantics to move an instance of A (which has been returned by another function) into the super-class A of B.
Effectively, you can promote A to B while making it possible to use a B as an A.
In contrast to Soonts' answer, my solution also works with added virtual tables, since it doesn't rely on unsafe pointer casting.
Another option, which may not be viewed as "clean" by some (though it is in my opinion) but still accomplishes the same thing, is using a static class. It's important to remember that when we create a member function, what's really happening behind the scenes is that the compile generates a function where the object (aka "this") is the first parameter. So, we can do the same thing to extend our class's functionality without deriving from it.
class Something
{
public:
Something()
~Something()
}
// In objective-c you may call this category Something+Utils
class SomethingUtils
{
// You can use a pointer, or a reference here, your call.
static int GetSomethingElse(Something *something, int parameter);
}
This will accomplish the same intent as a category: You extend the functionality of your class object, and you don't have to create a new derived class. You will not be able to access private or protected member functions and variables, but you can't do that in objective-c anyway, so there's nothing lost on that front (and if you are trying to use private or protected member state, you've missed the point of categories entirely). You wouldn't be able to use the . and -> operators, but in my opinion, that's a much better compromise than deriving a new type just to add some utility methods.
C++ has the inheritance for that. In addition, I've used the following trick a few times to extend classes generated by #import "progid:..." directive:
// This one is part of external framework, or auto-generated, or dllimport, or #import, etc..
class A
{
protected double m_x;
};
// This one is the extension class. Make sure you only add non-virtual methods here.
// Static methods and static data members are OK as well.
class __declspec( novtable ) B: public A
{
public:
double getSquare(){ return m_x * m_x; }
__declspec( property( get = getSquare ) ) double square;
};
// Usage example
double someFunc( A& arg )
{
B& b = static_cast<B&>( arg ); // Note we've not constructed any instance of B, just casted.
return b.square;
}
I got a nearly consistent calling convention with an idea I talked about in a lightning talk a year or so ago:
(the intro makes less sense without he commentary - wait til it gets to the C++ bit).
Note that the material was not intended to be taken seriously - although some, inevitably, have ;-)
First off, I know I can not do it, and I think it's not a duplicate questions (this and this questions deal with the same problem, but they only want an explanation of why it does not work).
So, I have a similar concept of classes and inheritance and I would, somehow, elegantly, want to do something that's forbidden. Here's a very simple code snippet that reflects what I want to do:
#include <iostream>
class A{
protected:
int var;
std::vector <double> heavyVar;
public:
A() {var=1;}
virtual ~A() {}
virtual void func() {
std::cout << "Default behavior" << this->var << std::endl;
}
// somewhere along the way, heavyVar is filled with a lot of stuff
};
class B: public A{
protected:
A* myA;
public:
B(A &a) : A() {
this->myA = &a;
this->var = this->myA->var;
// copy some simple data, e.g. flags
// but don't copy a heavy vector variable
}
virtual ~B() {}
virtual void func() {
this->myA->func();
std::cout << "This class is a decorator interface only" << std::endl;
}
};
class C: public B{
private:
int lotsOfCalc(const std::vector <double> &hv){
// do some calculations with the vector contents
}
public:
C(A &a) : B(a) {
// the actual decorator
}
virtual ~C() {}
virtual void func() {
B::func(); // base functionality
int heavyCalc = lotsOfCalc(this->myA->heavyVar); // illegal
// here, I actually access a heavy object (not int), and thus
// would not like to copy it
std::cout << "Expanded functionality " << heavyCalc << std::endl;
}
};
int main(void){
A a;
B b(a);
C c(a);
a.func();
b.func();
c.func();
return 0;
}
The reason for doing this is that I'm actually trying to implement a Decorator Pattern (class B has the myA inner variable that I want to decorate), but I would also like to use some of the protected members of class A while doing the "decorated" calculations (in class B and all of it's subclasses). Hence, this example is not a proper example of a decorator (not even a simple one). In the example, I only focused on demonstrating the problematic functionality (what I want to use but I can't). Not even all the classes/interfaces needed to implement a Decorator pattern are used in this example (I don't have an abstract base class interface, inherited by concrete base class instances as well as an abstract decorator intreface, to be used as a superclass for concrete decorators). I only mention Decorators for the context (the reason I want a A* pointer).
In this particular case, I don't see much sense in making (my equivalent of) int var public (or even, writing a publicly accessible getter) for two reasons:
the more obvious one, I do not want the users to actually use the information directly (I have some functions that return the information relevant to and/or written in my protected variables, but not the variable value itself)
the protected variable in my case is much more heavy to copy than an int (it's a 2D std::vector of doubles), and copying it in to the instance of a derived class would be unnecessarily time- and memory-consuming
Right now, I have two different ways of making my code do what I want it to do, but I don't like neither of them, and I'm searching for a C++ concept that was actually intended for doing something of this sort (I can't be the first person to desire this behavior).
What I have so far and why I don't like it:
1. declaring all the (relevant) inherited classes friends to the base class:
class A{
....
friend class B;
friend class C;
};
I don't like this solution because it would force me to modify my base class every time I write a new subclass class, and this is exactly what I'm trying to avoid. (I want to use only the 'A' interface in the main modules of the system.)
2. casting the A* pointer into a pointer of the inherited class and working with that
void B::func(){
B *uglyHack = static_cast<B*>(myA);
std::cout << uglyHack->var + 1 << std::endl;
}
The variable name is pretty suggestive towards my feelings of using this approach, but this is the one I am using right now. Since I designed this classes, I know how to be careful and to use only the stuff that is actually implemented in class A while treating it as a class B. But, if somebody else continues the work on my project, he might not be so familiar with the code. Also, casting a variable pointer in to something that I am very well aware that it is not just feels pure evil to me.
I am trying to keep this projects' code as nice and cleanly designed as possible, so if anybody has any suggestions towards a solution that does not require the modification of a base class every now and then or usage of evil concepts, I would very much appreciate it.
I do believe that you might want to reconsider the design, but a solution to the specific question of how can I access the member? could be:
class A{
protected:
int var;
static int& varAccessor( A& a ) {
return a.var;
}
};
And then in the derived type call the protected accessor passing the member object by reference:
varAccessor( this->myA ) = 5;
Now, if you are thinking on the decorator pattern, I don't think this is the way to go.
The source of the confusion is that most people don't realize that a type has two separate interfaces, the public interface towards users and the virtual interface for implementation providers (i.e. derived types) as in many cases functions are both public and virtual (i.e. the language allows binding of the two semantically different interfaces). In the Decorator pattern you use the base interface to provide an implementation. Inheritance is there so that the derived type can provide the operation for the user by means of some actual work (decoration) and then forwarding the work to the actual object. The inheritance relationship is not there for you to access the implementation object in any way through protected elements, and that in itself is dangerous. If you are passed an object of a derived type that has stricter invariants regarding that protected member (i.e. for objects of type X, var must be an odd number), the approach you are taking would let a decorator (of sorts) break the invariants of that X type that should just be decorated.
I can't find any examples of the decorator pattern being used in this way. It looks like in C++ it's used to decorate and then delegate back to the decoratee's public abstract interface and not accessing non-public members from it.
In fact, I don't see in your example decoration happening. You've just changed the behavior in the child class which indicates to me you just want plain inheritance (consider that if you use your B to decorate another B the effects don't end up chaining like it would in a normal decoration).
I think I found a nice way to do what I want in the inheritance structure I have.
Firstly, in the base class (the one that is a base for all the other classes, as well as abstract base class interface in the Decorator Pattern), I add a friend class declaration only for the first subclass (the one that would be acting as abstract decorator interface):
class A{
....
friend class B;
};
Then, I add protected access functions in the subclass for all the interesting variables in the base class:
class B : public A{
...
protected:
A *myA;
int getAVar() {return myA->var;}
std::vector <double> &getAHeavyVar {return myA->heavyVar;}
};
And finally, I can access just the things I need from all the classes that inherit class B (the ones that would be concrete decorators) in a controlled manner (as opposed to static_cast<>) through the access function without the need to make all the subclasses of B friends of class A:
class C : public B{
....
public:
virtual void func() {
B::func(); // base functionality
int heavyCalc = lotsOfCalc(this->getAHeavyVar); // legal now!
// here, I actually access a heavy object (not int), and thus
// would not like to copy it
std::cout << "Expanded functionality " << heavyCalc << std::endl;
std::cout << "And also the int: " << this->getAVar << std::endl;
// this time, completely legal
}
};
I was also trying to give only certain functions in the class B a friend access (declaring them as friend functions) but that did not work since I would need to declare the functions inside of class B before the friend declaration in class A. Since in this case class B inherits class A, that would give me circular dependency (forward declaration of class B is not enough for using only friend functions, but it works fine for a friend class declaration).