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.
Related
Regarding the size of the derived class, is it better to have a "chain" of inheritance or inherit everything in the lowest derived class?
for example, what is better between:
class Base {
virtual void something() = 0;
};
class Derived1 {
// ...
};
class Derived2 : public Derived1, public Base {
// ...
};
and
class Base {
virtual void something() = 0;
};
class Derived1 : public Base {
// ...
};
class Derived2 : public Derived1 {
// ...
};
In the second case, will it have to store two vtable pointers and just one in the first case?
In the first case, I have a sizeof(Derived) lower that in the second case.
What you're seeing as far as i can see is simply an empty base class optimization.
See the godbolt I've prepared. When you don't have empty classes, the sizes are identical.
https://godbolt.org/z/HhiJz6
To specifically address your question Regarding the size of the derived class, is it better to have a "chain" of inheritance or inherit everything in the lowest derived class?
I guess if you have an empty base class in there, you could claim it to be "better" in terms of size of the class, but that is pretty dependent on the specifics of the way the class is defined that could change at any time.
I wouldn't base an inheritance structure on it unless i was really pressed for space.
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.
Let's say I have an interface that inherits from another interface (pure abstract class)
class BaseInterface
{};
Then another interface builds upon BaseInterface
class ExtendedInterface : public BaseInterface
{};
Now, I have a concrete class that implements BaseInterface:
class Base : public BaseInterface
{};
Now, I want to implement ExtendedInterface, but since I already have Base I want to fill out the BaseInterface members with base. E.g.:
class Extended : public ExtendedInterface, public Base
{};
This doesn't seem to work. I get complaints that I cannot instantiate extended since it is an abstract class. The only way I can get it to work is by using virtual inheritance, but then I get compiler warnings about inheriting via dominance.
What's the problem ?
With your multiple inheritance, Extended inherits two times from BaseInterface. This means that there are two independent BaseInterface subobjects:
one is inherited via the concrete Base class, which has overridden all the pure virtual functions.
but the other is inherited via ExtendedInterface class, which is still abstract.
In consequence, as some subobjects of Extended still have pure virtual functions, your class is still an abstract class that can't be instantiated.
How to solve it ?
As despite the multiple inheritance you apparently expect to have only one BaseInterface, you need to use virtual inheritance:
class BaseInterface
{ virtual void test()=0; }; // abstract class
class ExtendedInterface : public virtual BaseInterface // virtual inheritance
{}; // abstract class
class Base : public virtual BaseInterface // virtual inheritance
{ void test() override {} }; // concrete class
class Extended : public ExtendedInterface, public Base // multiple
{}; // thanks to virtual inheritance, concerete class
With this logic, there will be only one BaseInterface in Extended, with virtual functions overridden, and you can instantiate it.
Here an online demo
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!
I would like to use interfaces in c++ like in java or in c#. I decided to use purely abstract classes with multiple inheritance, but something is terribly wrong when I specialize the interface:
class Interface
{
public:
virtual int method() = 0;
};
// Default implementation.
class Base: virtual public Interface
{
public:
virtual int method() {return 27;}
};
// specialized interface
class Interface2: public Interface
{
public:
virtual int method() = 0;
// some other methods here
};
// concrete class - not specialised - OK
class Class: public virtual Interface, public virtual Base
{
};
// concrete class - specialised
class Class2: public Interface2, public Base
{
};
int main()
{
Class c;
Class2 c2;
return 0;
}
Warning 1 warning C4250: 'Class' : inherits 'Base::Base::method' via dominance 30
Error 2 error C2259: 'Class2' : cannot instantiate abstract class 42
What is the proper way to do this?
Class2 inherits from an abstract class (Interface2) but does not implement the pure virtual method, so it remains as an abstract class.
Heh heh, this problem tickles something buried deep in my head somewhere. I can't quite put my finger on it but I think it's to do with defining an interface heirarchy and then inheriting both an interface and an implementation. You then avoid having to implement all functions with by forwarding calls to a base class. I think.
I think this simple example shows the same thing, but is maybe a bit easier to understand because it uses things that can be easily visualized: (please forgive the struct laziness)
#include <iostream>
using namespace std;
struct Vehicle
{
virtual void Drive() = 0;
};
struct VehicleImp : virtual public Vehicle
{
virtual void Drive()
{
cout << "VehicleImp::Drive\n";
}
};
struct Tank : virtual public Vehicle
{
virtual void RotateTurret() = 0;
};
struct TankImp : public Tank, public VehicleImp
{
virtual void RotateTurret()
{
cout << "TankImp::RotateTurret\n";
}
// Could override Drive if we wanted
};
int _tmain(int argc, _TCHAR* argv[])
{
TankImp myTank;
myTank.Drive(); // VehicleImp::Drive
myTank.RotateTurret(); // TankImp::RotateTurret
return 0;
}
TankImp has essentially inherited the Tank interface and the Vehicle implementation.
Now, I'm pretty sure this is a well known and acceptable thing in OO circles (but I don't know if it has a fancy name), so the dreaded diamond thing is ok in this case, and you can safely suppress the dominance warning because it's what you want to happen in this case.
Hope that somehow helps point you in the right direction!
BTW, your code didn't compile because you hadn't implemented the pure virtual "method" in Class2.
EDIT:
Ok I think I understand your problem better now and I think the mistake is in Interface2. Try changing it to this:
// specialized interface
class Interface2: public virtual Interface // ADDED VIRTUAL
{
public:
//virtual int method() = 0; COMMENTED THIS OUT
// some other methods here
};
Interface2 should not have the pure virtual defintion of method, since that is already in Interface.
The inheritance of Interface needs to be virtual otherwise you will have an ambiguity with Base::method when you derive from Interface2 and Base in Class2.
Now you should find it will compile, possibly with dominance warnings, and when you call c2.method(), you get 27.
Based on this comment
If the method is not reimplemented in Class2 or Class (it is not in
this case) Base::method() will be called. Otherwise the reimplementation
will be called. There is an interface hierarchy with a common base
dumb implementation.
– danatel 16 mins ago
That's not what you got, you don't have a common base, you've got
Interface -> Interface2 -> Class2
Interface -> Base -> Class2
The interface is not 'merged' in the derivation tree, interface2 does not inherit virtually from interface, so it'll have its own interface super class.
It's like the pure virtual method() exists twice in Class2, once implemented via Class, and once not-implemented.
And even if you had inherited virtually, the common base (Interface) still would not have an implementation
If Base contains trivial operations that should be usuable in the whole hierarchy, then why not have Base as your startpoint? (even if still pure virtual with an implementation).
If this was just a very simple example to make the question short, something like the Bridge Pattern might be more usefull. But it's hard to guide you further without knowing more.
You should also look at defining a virtual destructor in your Interface if you might be deleting using an Interface or Base pointer.
Without a virtual destructor you will have problems if you do something like:
Base *b = new Class2();
delete b;
Regarding Class: All you need to do is derive Class from Base -- the fact that it implements Interface is implied, and in fact, inescapable:
class Class: public Base // virtual inheritance is unnecessary here
{
};
Class will inherit method() from Base as desired.
Regarding Class2:
Disclaimer: Negative result ahead
Based on your comment on Tom's answer, I thought I had the answer for Class2:
// concrete class - specialised
class Class2: public Interface2, public Base
{
public:
using Base::method; // "Imports" all members named "method" from Base
};
But actually, this doesn't work. Grovelling through the C++ standard reveals that
section 7.3.3, paragraph 14 explains that using can't be used to resolve ambiguous accesses to inherited members:
... [Note: because a using-declaration designates a base class member (and not a member subobject or a member function of a base class subobject), a using-declaration cannot be used to resolve inherited member ambiguities. ...]
It seems that the only way to get the desired behaviour in Class2 is to manually forward the method:
// concrete class - specialised
class Class2: public Interface2, public Base
{
public:
virtual int method() { return Base::method(); }
};
Regarding virtual inheritance: You don't need it for Class's declaration, but you probably do need it for Interface2's declaration to ensure that Class2 only has a single subobject of type Interface -- as it stands, every Class2 object has two subobjects of this type. (Although that won't cause problems if Interface is in fact a pure interface, lacking member variables.) If it helps, draw a diagram: every time a base class appears without the keyword virtual, it appears as a distinct object; all base classes that appear with the keyword virtual are condensed into one object.
[UPDATE: markh44's excellent answer shows that the above approach (of making Interface2 inherit virtually from Interface) will in fact allow Class2 to automatically inherit the implementation of method() from Base! Problem solved!]
This answer in a different forum seems to tackle the exact problem you mention.
In general, you should avoid the diamond inhertance pattern:
Interface
/ \
Base Interface2
\ /
Class2
This will cause you call kinds of grief down the road if you're not careful. Ambiguity will bite you.
In your specific instance there's no need for Interface2 to inherit from Interface. Interface2 doesn't need to specify "method" since it's abstract. Remove the inheritance between Interface and Interface2 to break the diamond. Then you're hierarchy looks like:
Interface Interface Interface2
| | |
Base Base |
| \ /
Class Class2
And your implementation looks like:
// concrete class - not specialised - OK
class Class: public Base
{
};
// concrete class - specialised
class Class2: public Base, public Interface2
{
virtual int method() {return 35;}
virtual void Inteface2Method { ... }
};