Multiple inheritance - c++

I have 2 base classes (B1 and B2) which are derived from common Base class(B), where they have a common variable (let: int x; from base B), in 1st base x=0, in the 2nd base x=10 (default values given in B1,B2 constructors).
Visually:
class B
{
int x;
protected:
B(int x) : x{x}{}
};
class B1 : public B
{
protected:
B1() : B(0){}
};
class B2 : public B
{
protected:
B2() : B(10){}
};
Now if I derive one more class:
class D : virtual public B1, virtual public B2
{
public:
D() : B1{}, B2{}{}
};
Here only one copy of x will be available as per virtual concept, now if I try to access x value with derived class object which instance of x I will get in O/p (x=0 or x=10), and why?

In order to use virtual inheritance, base B must be declared as virtual in both B1 and B2. Without that, you have non-virtual inheritance of B.
If you have non-virtual inheritance, then you have two B bases in D, so you can't access x in D without qualifying it as B1::x or B2::x
If you have virtual inheritance, then you only have one B and one x, so the two assignments to it (x=0 and x=10) will happen in whichever order you did them in, and whichever one was later will overwrite the value set by the earlier one (much as with a simple variable x with two assignments).

In your setup as you have it, B is not actually inherited virtually, because you would have to declare virtual inheritance for B in both B1 and B2 (it always has to happen at the lowest level if the two "branches" are expected to be merged higher up in the class inheritance hierarchy), i.e.
class B1 : virtual public B
{
protected:
B1() : B(0){}
};
class B2 : virtual public B
{
protected:
B2() : B(10){}
};
If you do that, initialization of B would be completely different, because there are special rules for the construction of virtual base classes:
In virtual inheritance, the virtual base class is always initialized by the most derived class. Thus, as you have implemented the constructor of D as
D() : B1(), B2(){}
and therefore don't call your B constructor explicitly, the compiler will assume that you want to call Bs default constructor. But your class B does not have a default constructor, so you would get a compiler error like this:
prog.cpp: In constructor ‘D::D()’:
prog.cpp:31:20: error: no matching function for call to ‘B::B()’
D() : B1(), B2(){}
^
Therefore, you would have to do something like
class D : public B1, public B2
{
public:
D() : B(99), B1(), B2(){}
};
and this also solves your question: The value of x will be whatever the most derived class wants it to be (99 in this case). Thus, there is no ambiguity.
PS: You also see, your question is at the heart of why it makes sense to have the special rule about virtual base class construction by the most derived class.

Related

c++ Multiple inheritance and casting

I have the following classes :
class A { };
class B {
public:
B(){}
virtual ~B(){};
};
class B1 : public B{
public:
B1(){}
virtual ~B1(){};
};
class B2 : public B{
public:
B2(){}
virtual ~B2(){};
};
class C1 : public A, public B1{
public:
C1(){}
virtual ~C1(){};
};
class C2 : public A, public B2{
public:
C2(){}
virtual ~C2(){};
};
I want to know if an object of type B is also of type A :
B*b = new C1(); // or new B, or new C2 ...
if(dynamic_cast<A*>(b))
{
...
Is my dynamic_cast the correct way do that (it compiles and it runs)?
Thank you.
To be able to use dynamic_cast all parents of the object needs to be polymorphic. I.e. you need to add at least one virtual function to the A class (like the destructor).
Once you fix that then your dynamic_cast is fine.
Class A is different than Class B in the C++ type system. Since they are both empty, they should be same however they are instatiated in memory. Even empty classes have the identity property.
dynamic_cast<new_type> (expression) commonly is used as: dynamic_cast<derived_type> (myBase). In this case "If expression is a pointer or reference to a polymorphic type Base, and new_type is a pointer or reference to the type Derived a run-time check is performed:" see cppreference.com search for dynamic_cast. This allows you to cast the base class back down to the derived class. The programmer must know that the derived class exists.

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.

virtual inheritance from base struct

struct A {
int i;
virtual void f() { cout << i; }
A() { i = 1; }
A(int _i) : i(_i) {}
};
struct B : A {
B() : A(2) { f(); }
void f() { cout << i+10; }
};
struct C : B, virtual A {
C() : A() {}
};
Can you please explain why in the C structure there will be two A::i and why there will be two vptr pointers to 'virtual tables methods' for C structure although A only has virtual method ?
I know when there is virtual inheritance from a common base there will be one instance of the common base not two ,Please advise!
Without virtual
When inheriting without virtual, you can imagine the memory structure to be like this:
class B : A {};
The variables of A are "inside" (just above) the variables of class B.
With virtual
When inheriting with virtual, B just has a "pointer" to A:
class B : virtual A {};
Your example
This means, your example looks like this:
class B : A
class C : B, virtual A
Only one instance of A
If you only want one instance of A, you have to use virtual two times:
class B : virtual A
class C : B, virtual A
vptr's
Here is the layout of your code as it was produced by g++ (generated with -fdump-class-hierarchy):
Class C
size=16 align=4
base size=8 base align=4
C (0xb7193440) 0
vptridx=0u vptr=((& C::_ZTV1C) + 12u)
B (0xb719f078) 0
primary-for C (0xb7193440)
A (0xb719a428) 0
primary-for B (0xb719f078)
A (0xb719a460) 8 virtual
vptridx=4u vbaseoffset=-12 vptr=((& C::_ZTV1C) + 28u)
I'm a bit rusty what concerns vpointers and vtables, so I'm not sure why there are exactly those v-pointers.
However, I can tell you, that your assumption that there is only one virtual method is wrong.
Because B inherits from A and A::f() is virtual, the derived B::f() is automatically also virtual, even if you don't explicitly write this down.
edit:
After digging a bit, I think I remember which v-pointers are needed and which are not.
However I won't give you any guarantee about the following.
In the following, the notation C.B.A means the A-subobject in B, which is in C, to distinguish the both A-subobject (C.B.A and C.A).
Each subclass needs a v-pointer. However *(C.B.A), *(C.B) and *C all point to the same location (namely the beginning of the class C which is also the beginning of C.B and C.B.A, therefore they can share one v-pointer. However a pointer to the subclass *(C.A) will point to a different location, therefore another vpointer is needed there. Also note that the subclass C.B.A won't even be accessible in your example (gcc: "warning: direct base ‘A’ inaccessible in ‘C’ due to ambiguity").
To make it a bit clearer:
If you only had the following structure
class B : A {};
class C : B {};
only one vpointer would be needed as all pointers to any subclass of C would point to the same location. The vpointer would only have to point to the vtable of either A, B or C to tell which is the run-time type of the object.
B isn't inheriting virtualy.
So you have the A struct inherited from B and another inherited virtauly.

How is this initialization list implemented using a virtual class?

#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?

c++ inheritance: error C2614 calling base class' constructor

I have a base class 'A' which has a subclass 'B' which has a subclass 'C' which has a subclass 'D'.
I want D to call 'A's constructor,
D(int x,int y):A(x,y){};
but I am getting the error message:
error C2614: 'D' : illegal member initialization: 'A' is not a base or member.
D can call any of 'C's constructors fine but that is not what I want.
Any help would be super appreciated.
You're stuck, that's the way C++ works - you only get to call the constructor of your immediate parent. You can daisy chain them so that D calls C's constructor which calls B's constructor which calls A's constructor.
D(int x,int y):C(x,y){};
C(int x,int y):B(x,y){};
B(int x,int y):A(x,y){};
As Mark Ransom's answer states, a derived class is only allowed to call its base class' constructor.
In your case, you can solve the problem by passing along the constructor arguments to D down the inheritance hierarchy until A's constructor is called by B with those arguments.
Another option is to create a protected function, say A::init( args ) that can be called by D directly.
In addition to the option of passing arguments down the inheritance hierarchy or having a protected member function in the base class, you could also solve this by using virtual inheritance. With virtual inheritance all base class constructors are called directly from the derived class so you don't have to go through the inheritance chain.
class A
{
public: A(){}
public: A(int x, int y){}
};
class B : public virtual A
{
public: B(){}
};
class C : public virtual B
{
public: C(){}
};
class D : public virtual C
{
public: D(int x,int y):A(x,y){};
};