virtual inheritance - c++

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!

Related

c++ virtual inheritance difference

Given two classes with a common virtual base class:
class Base {};
class Derived1 : public virtual Base {};
class Derived2 : public virtual Base {};
Is there any difference between these two further derived classes?:
class Derived3 : public virtual Base, public Derived1, public Derived2 {};
class Derived3 : public Derived1, public Derived2 {};
The first also derives directly from the virtual base class, but I think that has no effect, because it's shared with Derived1 and Derived2.
They say the same thing. The only difference is that if you removed public Derived1 and public Derived2 from both definitions of Derived3, the first one would still inherit from Base and the second one would not.
EDIT: I haven't thought carefully about whether there is some weird cross-cast situation where the two would also behave differently, although I don't think there is.
There is no difference between those examples.
But in a more complicated scenario, directly inheriting an otherwise inherited virtual base might change the order of construction / destruction of the base class subobjects.
I do not think there is any difference in object layout because the intention of virtual inheritance is to avoid having two copies of Base (or three copies in case 1).
So all the difference is in your intentions and really readability of the code.

virtual inheritance and base class of base class

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.

Can you inherit the same class twice?

Can you inherit the same class twice? E.g. :
class Base {
};
class Foo : public Base {
};
class Bar : public Base {
};
class Baz : public Foo, public Bar {
//is this legal?
// are there restrictions on Base
// (e.g. only virtual methods or a virtual base)?
};
Yes it is legal, and no there are no restrictions on Base.
You should however be aware that this causes two different objects of type Base to exist within Baz, which will require you to use qualified names to tell C++ which version of Base you mean, when you try to access its members.
C++ provides a mechanism called virtual inheritance to solve this problem (if it is a problem for you):
class Base { };
class Foo : public virtual Base { };
class Bar : public virtual Base { };
class Baz : public Foo, public Bar { };
This will share the Base object between the Foo and Bar objects within Baz
C++ does support multiple inheritance.
The syntax for class Baz is correct.
See this tutorial for some caveats and more information: http://www.cprogramming.com/tutorial/multiple_inheritance.html
Yes, it's legal to inherit the same class twice.
If the inheritance is non-virtual, as in your example (I just fixed the syntax and formatting),
class Base {};
class Foo : public Base {};
class Bar : public Base {};
class Baz : public Foo, public Bar {};
then it's generally necessary to qualify any use of something from such duplicate base.
If however each direct inheritance of the common base is virtual (using the keyword virtual), then there is only one common sub-object of the common base. This is the so called diamond pattern of inheritance in C++. It's a bit tricky, e.g. in that it yields at least one sub-object spread over a non-contiguous region of memory, and in that it's the most derived class that is responsible for initializing the common virtual base. Also it introduces some inefficiency and is associated with some compiler bugs. So it's seldom used, but sometimes it's necessary – e.g., it can emulate Java interface inheritance, and it can be used to emulate Java final (not necessary in C++11).
Yes, it is legal, but having two subobjects of the same Base class causes many difficulties, because you always must explicitly say which one you want, using the scope operator ::.
Baz x;
Base& y = x; // Illegal because ambiguous.
Base& y = (Bar&)x; // Now unambiguous.
Part of that trouble can be solved by inheriting Base using virtual inheritance, which makes sure only exactly one Base.subobject exists.
In that case, the virtual base is always initialised by the most derived constructor, before all non-virtual bases.
class Base {}
class Foo : public virtual Base {}
class Bar : public virtual Base {}
class Baz : public Foo, public Bar {}
Baz x;
Base& y = x; // Legal, because even though both direct bases inherit from `Base`,
// they do so virtually, thus there is only one Base subobject
Base& y = (Bar&)x; // Still unambiguous.
Now, if Foo used protected or private inheritance, you could not cast down to Foo::Derived in Baz or completely outside in the first (non-virtual) example.
In the virtual example, you could, because that sub-object is also reachable using Bar, and the most accessible path determines the access rights.
This is legal.
But restrictions arise when classes are labeled protected and private classes before it. For this, its respective functions and attributes are protected and private.

c++ why does virtual inheritance allow for the prevention of further inheritance?

Related: Does "virtual base class in the case of multilevel inheritance" have significance
I have a template class that can be inherited from in order to impart some select functionality. However, it wants to prevent any classes from further inheriting from anything that inherits it.
The following seems to achieve this:
template<typename Child>
class SealingClass
{
public:
/*public methods etc*/
private:
SealingClass() {}
friend Child;
};
//simplify a bit:
#define Seal( x ) public virtual SealingClass< x >
Now, I can inherit from the above class, as follows:
class NewClass: Seal(NewClass) {};
And if I then try inheriting again from NewClass, as in:
class AnotherClass: public NewClass {};
and then make an instance of said class:
AnotherClass a;
I get the desired error, regarding the constructor in SealingClass being private.
So, everything works as I'd like!
However, I have noticed that if I remove the virtual keyword from the define..
#define Seal( x ) public SealingClass< x >
..my instantiation of AnotherClass now works just fine.
I understand that the virtual keyword, in this context, means that only one instance of the base class is defined in cases of multiple inheritance (eg diamond inheritance) where multiple instances of it could exist, leading to ambiguous function calls etc.
But, why does it affect the functionality of the above?
Thanks :)
If use virtual inheritance, the most-derived type has to do the initialization of this virtual base class. If you don't use virtual inheritance, the directly derived type has to do the initialization.
Therefore, the private ctor does not prevent the derived type NewClass from initializing the direct base class SealingClass, and AnotherClass does not have to initialize NewClass if it's not been virtually inherited.
Some examples:
template<typename Child>
class SealingClass {
public: // for now
SealingClass() {}
};
class NewClass : public SealingClass<T> {
public:
NewClass() : SealingClass<T>() {} // allowed, SealingClass<T> is a
// direct base class
};
class AnotherClass : public NewClass {
public:
AnotherClass() : NewClass() {} // allowed, NewClass is a
// direct base class
AnotherClass() : SealingClass<T>() {} // not allowed, SealingClass<T> is
// no direct nor a virtual base class
};
class NewClass_v : public virtual SealingClass<T> {
public:
NewClass_v() : SealingClass<T>() {} // allowed, SealingClass<T> is a
// direct base class
};
class AnotherClass_v : public NewClass_v {
public:
AnotherClass_v() : NewClass_v() {} // allowed, NewClass_virt is a
// direct base class
AnotherClass_v() : SealingClass<T>() {} // allowed, SealingClass<T> is a
// virtual base class
};
Now, if the ctor of SealingClass is private, AnotherClass_virt is not allowed to call this ctor due to the private access specifier and not being a friend.
If you leave out the explicit initialization of a base class (whether virtual or direct), it is default-initialized ([class.base.init]/8), that is, the default ctor is called implicitly (but you still must have access to the ctor, so it's the same as explicitly writting the call to the default ctor).
Some quotes:
[class.base.init]/1
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
[class.base.init]/7
A mem-initializer where the mem-initializer-id denotes a virtual base class is ignored during execution of a constructor of any class that is not the most derived class.
[class.base.init]/10
In a non-delegating constructor, initialization proceeds in the following order:
First, and only for the constructor of the most derived class, virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
Emphasis mine.

Does "virtual base class in the case of multilevel inheritance" have significance

Consider the following sample codes which shows multilevel inheritance:
Case1 : Here the class derived1 is derived from the class base through virtual inheritance and the class derived2 is derived from the class derived1 directly.
class base
{
};
class derived1 : virtual public base
{
};
class derived2 : public derived1
{
};
Case2 : Same as Case1 except that no virtual inheritance is involved
class base
{
};
class derived1 : public base // no virtual inheritance
{
};
class derived2 : public derived1
{
};
Suppose i create an object of the class derived2 in both cases.
How does Case1 and Case2 differ with respect to the containment of sub-objects with in the object of derived2?
Does Case1 have significance over Case2 ?
PS: I am clear with the importance of a virtual base class during multiple inheritance.
Without multiple instances of a base class in an inheritance hierarchy there are (at least) two other issue to consider with virtual base classes.
First, a virtual base class is always initialized by the most derived class under construction and before non-virtual base classes. This is most obvious when intermediate classes pass parameters to the virtual base class constructor in their member initialization lists. These initializers will be ignored. It can also make a difference to the order of construction of base classes.
Second, it is not possible to perform a static_cast from a virtual base class to a class that inherits from it.
There is additional information stored when using virtual inheritance. This is to allow dynamic casts to properly resolve to derived classes in the case of a diamond situation. Your code does not have a diamond situation, so the information is not used.
The additional information can be made visible if you add a data member to the base class:
class base {
protected:
int i;
};
If you now print the size of each of the derived classes in each of your two cases, you will observe a difference in their sizes from one case to the other.
Edit: Charles Bailey makes excellent points about semantic differences with using virtual inheritance. His first point is particularly interesting, and should be given more consideration. His point is basically that derived2 has an implicit diamond topology. That is, assuming derived1 virtually inherits from base:
class base {};
class derived1 : virtual public base {};
Then, there is no difference between these three versions of derived2, they all behave like the first one:
class derived2 : virtual public base, public derived1 {};
class derived2 : public derived1, virtual public base {};
class derived2 : public derived1 {}
This implies that there is an implicit diamond created when you derive from a class like derived1 (that is, one that has used virtual inheritance).
base
| \
| \.(virtual)
| / \
| /___\
| |
| derived1
| /
| /
|./
/ \
/___\
|
derived2
To further illustrate the point, this is allowed when derived1 uses virtual inheritance:
class derived2 : public derived1 {
public:
derived2 () : base() {}
};
But, it is not allowed if derived1 does not use virtual inheritance.
Virtual inheritence has no significance in your case.
It is only indented for diamon inheritence like:
B: A
C: A
D: B, C
In this case inheritence from A in both cases should be virtual.
Virtual inheritance becomes significant only when the class is included as a base class more than once. In fact the specifier virtual means here "include only once".
When you do not have multiple inheritance you cannot specify the same class several times (circular inheritance is a clear syntax error). Then it comes to how good smart is the optimization in your compiler. If the compiler is perfect, then there is no difference. Practically speaking you pick up the risk that compiler will add something that has relation to multiple inheritance to your class. The less often some feature of the language is used, the bigger the risk that compiler will get confused. Compiler is typically a high quality program, but still this is only a program.