Consider the following code:
class A {
};
class B : public A {
};
class C : public B{
public:
C() : A() {} // ERROR, A is not a direct base of B
};
In this case GCC (4.8.1, C++99) gives me the correct error (I understand this behavior):
prog.cpp:12:8: error: type āaā is not a direct base of ācā
However if the inheritance between b and a is virtual, this does not happen:
class A {
};
class B : virtual public A {
};
class C : public B{
public:
C() : A() {} // OK with virtual inheritance
};
Why does this work?
Is A now considered a direct base to C by the compiler?
In general, because this is how C++ tries to resolve the diamond inheritance problem http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem (whether or it is a good or bad solution is left as an exercise to the reader).
All inheritance is a combination of an is-a and a has-a relationship...you must instantiate an instance of the parent. If you have the following classes:
class a;
class b : a;
class c : a;
class d : b,c;
Then you've instantiated an a for each b and c. d will not know which a to use.
C++ solves this by allowing virtual inheritance, which is high-overhead inheritance that allows b and c to share the same a if inherited in d (it is much more complicated than that, but you can read up on that on your own).
The most derived type in the chain needs to be able to override the instantiation of the shared class to control disparities in the way that the shared class is inherited in the parent classes. Take the following example:
class a {int x; public: a(int xx) {x=xx;} int get_x() {return x;}};
class b : public virtual a { public: b(): a(10){}};
class c : public virtual a { public: c(): a(15){}};
class d : public virtual b, public virtual c {public: d() : a (20) {}};
int main() {
d dd;
std::cout << dd.get_x() << std::endl;//20, d's constructor "wins"
return 0;
}
If d did not define what a was instantiated as, it would have definitions for conflicting instantiations (from b and c). C++ handles this by forcing the most derived class in the inheritance chain to instantiate all parent classes (the above would barf if d did NOT explicitly instantiate a, though if a supplied a default constructor that could be implicitly used) and ignoring all parent instantiations.
Why does this work?
According to the standard (10.1.4 in the FIDS), "for each distinct baseclass that is specified virtual, the most derived object shall contain a single base class subobject of that type".
Virtual base is shared between all classes that derive from it for the instance of the object. Since a constructor may only be called once for a given instaniation of an object, you have to explicitly call the constructor in the most derived class because the compiler doesn't know how many classes share the virtual base. This is because the compiler will start from the most base class's constructor and work to the most derived class. Classes that inherit from a virtual base class directly, will not, by the standard, call their virtual base classes constructor, so it must be called explicitly.
From N3337, 12.6.2
Initializing bases and members
In the definition of a constructor for a class, initializers for direct and virtual base subobjects and non-static data members can be specified by a ctor-initializer, which has the form
Perhaps someone who has better version of Standard can verify this.
Related
class A: public B, public C { };
In this case order of execution is:
B(); // base(first)
C(); // base(second)
A(); // derived
class A: public B, virtual public C { };
But in this case,when i write virtual with class c while inheriting,order of
// execution becomes:
C(); // virtual base
B(); // ordinary base
A(); // derived
i have read somewhere that order of calling constructor depends on the order of declaration while inheriting multiple classes but how does the order of execution gets changed on writing virtual with a class.I am not able to get why i am getting such result.
The virtual base class constructors are always executed first according to the C++ standard. From the working draft N3242, page 272 line 10, we learn that:
Virtual base class constructors go first, in the order of a left-to-right depth-first traversal of the inheritance graph.
Direct base classes go next, in declaration order.
So the behavior you see is exactly what is required in the C++ standard. It makes sense, because the virtual base classes may show up multiple times in the inheritance and of course they can each only be constructed once. Hence there has to be an initial round of virtual base class construction, followed by the usual non-virtual base class construction.
There is also a nice explanation on this page.
If you have a virtual class as a parent, you cannot hope that initialization goes always in the order of declaration. In fact it is possible that the first (say non-virtual) parent class has itself a dependency on the virtual class. Hence in that case the virtual class must be constructed first.
I think this is the reason why C++ specification says that initializers of virtual parent classes get always executed first. As shown by #Dan Roche there is a predictable order of initialization.
Example:
class B: public A {...}
class C: public B, virtual A {...}
In this example in C's initialization it is not possible to initialize B before A since B's initialization requires A to be initialized first.
another example
This example is to show that you shouldn't rely on base class initialization order:
#include <iostream>
using namespace std;
struct A {
A() {cout<<"A()"<<endl;}
};
struct B {
B() {cout<<"B()"<<endl;}
};
struct C: virtual A, virtual B {
C() {cout<<"C()"<<endl;}
};
struct D: virtual B, virtual A, C {
D() {cout<<"D()"<<endl;}
};
int main() {
cout<<"construct C"<<endl;
new C;
cout<<"construct D"<<endl;
new D;
}
output:
construct C
A()
B()
C()
construct D
B()
A()
C()
D()
As the example shows, when C is constructed as a base class of D, the order of initialization of A and B is reversed. This means that you cannot rely on the order of initialization of virtual base classes if you want that somebody could extend your class.
I'm having this kind of code:
class Ref {<undefined>};
Ref refObjectForA, refObjectForB;
class Base
{
public:
Base(const Ref & iRef) : _ref(iRef) {}
virtual ~Base() {}
const Ref & ref;
};
class A: public Base
{
public:
A() : Base(refObjectForA) {}
virtual ~A() {}
};
class B: public A
{
public:
B() : Base(refObjectForB) {} // won't compile: Base is not direct base of B
virtual ~B() {}
};
As the attribute is a reference, I think I can only set it in constructor, so I need to call Base constructor in B().
I've found two ways: providing a "forward" constructor in A (but this implies adding code in all classes that might be inherited):
A(const Ref& iRef): Base(iRef)
or using virtual inheritance:
class A: public virtual Base
Second option allows more straightforward code in B implementation but I'm wondering if I'm misusing virtual inheritance in an ugly trick or if it is a valid usecase.
Can I use virtual inheritance in this case?
If no, for what reason?
One of the "unexpected" behaviors I've found is that it's not possible to static_cast a Base pointer to a B pointer because of the virtual inheritance.
Moreover I'm also wondering why it works (I mean why a B().ref == refObjectForB): I would think that the implicit call to default A() constructor in B() would overwrite the ref attribute after explicit Base constructor, but maybe it's not true with virtual inheritance.
The best option I can see if you want to stick to your inheritance hierarchy is to implement protected constructors taking a reference which they'll forward to the Base class. Making a constructor protected makes sure that a (final) instance can't be constructed using this constructor, so it will only be used in subclasses to initialize the super classes.
With some more or less ugly and dangerous macro, this becomes easy to be written:
#define REF_FORWARD_CTOR(ClassName, DirectSuperClassName) \
protected: ClassName(class Ref &r) : DirectSuperClassName(r) {} \
public:
class A : public Base
{
REF_FORWARD_CTOR(A, Base)
public:
A() : Base(refObjectForA) {} // normal ctor
};
class B : public A
{
REF_FORWARD_CTOR(B, A)
public:
B() : A(refObjectForB) {} // normal ctor
};
An alternative design would be to let A and B both derive (directly) from Base. Then, add functionalities by using multiple inheritance and "common classes", maybe private, depending on what they are for:
class Base {
};
class Common {
// common stuff used by both A and B
};
class A : public Base, public Common {
// no further stuff here
};
class B : public Base, public Common {
// add more stuff, or put it in a common super-class again,
// if some classes want to inherit from B again
};
The problem with this design is that functionality in Common can't access the stuff in A and B. To solve this, do one of the following:
If only static stuff is required: Use CRTP to specify A / B in a concrete Common type: Common<A> can then use A::..., but doesn't have anything to do with a concrete instance of A
If an instance is required: provide a pointer / reference in the constructor of Common (slight overhead)
Putting the first two solutions together: Use CRTP, implement wrapper functions in A and B which call functions in Common<A> and Common<B> providing this (which is a A* or B* via an extra parameter.
Same as above, but the class Common can also be non-templated (no CRTP) if you overload / template these functions on this pointer argument ("CRTP on functions", if you want to call it like that). Code speaks louder than words. (Example code is without your references and focuses on the "common class".)
Yes you can technically use virtual inheritance to achieve the goal of providing the reference in the most derived class.
And yes, that's a design smell.
Your classes should not need to be aware of anything but their immediate bases (virtual inheritance is the exception to the rule, when it's needed for other reasons).
Sticking to the proposed classes hierarchy, in order to solve the problem it is enough to use the "using-declaration" to bring the Base's constructor to the protected part of the class A, i.e.:
class A: public Base
{
public:
A() : Base(refObjectForA) {}
virtual ~A() {}
protected:
using Base::Base;
};
#include<iostream.h>
class A{
public:
int i;
A(int j=3):i(j){}
};
class B:virtual public A{
public:
B(int j=2):A(j){}
};
class C:virtual public A{
public:
C(int j=1):A(j){}
};
class D:public B, public C {
public:
D(int j=0):A(j), B(j+1), C(j+2){}
};
int main()
{
D d;
cout<<d.i;
return 0;
}
I am not being able to understand how the final output is zero. Every time j is initialized in default way to some fixed value, how is the value initialized in the constructor of class D being passed to class A?
Since A is a virtual base class, it should be constructed only once, so it is not possible to create it with different constructor parameters, and the C++ compiler has to choose one way of creating a base class.
The obvious question is: which one is used?
And the rule is: the one specified in the most derived class that inherits A directly.
The initialization order is simple: first A (with the parameter value from D constructor initialization list), then B (it is D's first ancestor; and it uses the instance of A created before), then C (and it shares the same A instance), finally D (and it also shares the same A object as B and C).
The rule with virtual base inheritance is:
"The most derived class in a hierarchy must construct a virtual base"
In your case, from the most derived class D You explicitly called the constructor of A by passing an argument 0 So it sets the i to 0. As mentioned in rule virtual base class is constructed through most derived class only and the other constructor calls through intermediate hierarchy have no effect since it is only constructed once.
The order of calling is:
A(int)
B(int)
C(int)
Good Read:
Why virtual base class constructors called first?
Say we have a class inheriting from two base classes (multiple inheritance). Base class A is abstract, declaring a pure virtual function foo, the other base class B declares and implements a function foo of the very same signature.
struct A
{
virtual void foo(int i) = 0;
};
struct B
{
virtual void foo(int i) {}
};
struct C : public A, public B {};
I want to use the implementation of foo from base class B in my derived class C. However, if I do not implement the function foo a second time in my derived class C, I cannot instantiate any object of it (it remains abstract). Virtual inheritance does not help here as expected (class A and class B have no common base class).
I wonder if there is a way to "import" the implementation of foo from class B into class C in order not to have to repeat the same code.
Above example is of course contrived. The reason I want implement foo in class B is that I want to derive class D : public B and use class Bs implementation of foo. I know that inheritance is not (primarily) intended for code reuse, but I'd still like to use it in that way.
In java, your sample code works. In C++ it doesn't. A subtle difference between those languages.
Your best option in C++ is to define C::foo() by forwarding to B::foo():
struct C : public A, public B
{
virtual void foo(int i) { B::foo(i); }
};
If I have something like
class Base1 {};
class Base2 {};
class Derived : public Base1, public Base2 {};
Then order of constructor call on making object of Derived is
Base1
Base2
i.e in the order they appear in
class Derived : public Base1, public Base2 {};
But If I change it to
class Derived : public Base1, virtual public Base2 {};
Then Order of constructor call becomes
Base2
Base1
I am not able to understand why this is so ?
Another simple doubt:
what can be the meaning and purpose of inheriting Base1 virtually.
Those are just the rules. The most derived class being constructed initializes all the virtual base classes in the hierarchy first before starting the initialization of its non-virtual direct bases.
The rules come from the standard (ISO/IEC 14882:2011), section 12.6.2 [class.base.init] / 10.
A rationale for this approach would be that it ensures that all base classes are initialized before their derived classes whether or not they are virtual bases.
On the order of initialization, Charles has already answered properly: those are the rules, first the virtual bases in the order of declaration, then the non-virtual bases in the order of declaration, then member variables in the order of declaration.
What is the meaning of virtual inheritance? It means that your object derives from that particular base, but that if in a hierarchy more than one subobjects (bases of the complete type) inherit virtually from the same base type, only one base subobject will be present. You can read the virtual keyword there as I am willing to share my base with other objects in the complete type.
struct ubase {};
struct sbase {};
struct A : ubase, virtual sbase {}; // has a sbase subobject, but is willing to share..
struct B : ubase, virtual sbase {}; // ... but want to have my own ubase
struct C : A, B {}; // only one sbase subobject, shared by A and B
// ... but two ubase subobjects, A::ubase and B::ubase
As per the second question, when do you want to use virtual inheritance? Whenever in a type hierarchy you might end up inheriting from the same base more than once and in your design all those occurrences of the base class are just one. In general, it is quite uncommon to use virtual inheritance other than in a few particular cases.
As for inheriting virtually. It comes into play when you have a derived class like below
class A {};
class B : public virtual A {} ;
class C : public virtual A {} ;
class D : B, C { } // this class has only one instance of A!
aka the diamond problem!