I understand that virtual inheritance of a base class creates a common shared base class among multiple derived classes, thus addressing the DDD problem. If I have only one derived class for my base class, is there a difference when I inherit the base virtually or non-virtually ? Basically I am trying to understand explanation provided in the query Is it possible to forbid deriving from a class at compile time? where Usage_lock base class is inherited virtually to prevent derivations from the class Usable. If I remove this virtual key, the behaviour changes i.e. I am able to derive subclasses from Usable. So I want to understand difference cause by virtual key in single inheritance scenarios.
The primary difference in a single virtual inheritance case is that only the most-derived class calls the constructor of virtually inherited bases, and all of the other classes are provided a reference to the constructed class (this happens behind the scenes).
So, in the example, the since attempting to further derive Usable would require the new class to call the Usable_lock constructor (which is private), it is impossible for any other classes to be derived from Usable. Only Usable is allowed to construct the lock object, due to it being a friend of the lock.
Virtual Inheritance was basically introduced to solve the classical problem of Diamond shaped Inheritance.
Consider, the following classes:
class Base {};
class Derived1: Base {};
class Derived2: Base {};
struct MostDerived: Derived1, Derived2 {};
MostDerived class here has 2 instance of Base because of this diamond shaped hierarchy.
To solve this problem, C++ uses the virtual keyword and introduces the concept called Virtual Inheritance.
Thus adding the virtual keyword here, as:
class Derived1: virtual Base {};
class Derived2: virtual Base {};
Ensures that now there will only be one instance of Base inside MostDerived class.
And the MostDerived class instantiates this instance of Base class by calling its constructor.
With the above background(emphasized bold text), consider the following for the code example:
Usable class derives virtually from Usable_lock, so the derived class Usable MUST instantiate the Usable_lock base class of the object by calling its constructor.
But Usable_lock class has an private constructor so only the class itself can access the constructor, thus preventing other classes from deriving from it.
Reference from the C++03 Standard:
Section 12.6.2 Initializing bases and members
Paragraph 6:
All sub-objects representing virtual base classes are initialized by the constructor of the most derived class(1.8). If the constructor of the most derived class does not specify a mem-initializer for a virtual base class V, then V’s default constructor is called to initialize the virtual base class subobject. If V does not have an accessible default constructor, the initialization is ill-formed. A mem-initializer naming a virtual base class shall be ignored during execution of the constructor of any class that is not the most derived class.
A virtual base class will be constructed by the most derived class. By deriving virtually, and making the constructor of such base private, there is no way another class may construct it, hence effectively preventing derivation. However, its quite an artificial construct, and it comes with some overhead too.
Related
I have a similar situation to this question where I have 2 classes that share a public interface function, and so I've pulled that function (manage_data_in_memory() in the example) out into a base class which the 2 classes inherit from. However, the 2 classes are otherwise not related, and one of them is polymorphic, whereas the other one isn't. It is also not expected for someone to declare an object of this base class, as it exists only to prevent code duplication (is there a way to enforce this? I know pure virtual functions can prevent an object from being instantiated, but declaring a dummy pure virtual that does nothing in the derived class seems like bad design).
Does the base class destructor need to be virtual in this case? This would force the other derived class to also have a virtual destructor, which it doesn't need.
Thanks.
So now I have code in the form
class base { // don't instantiate an object of this, is there a way to enforce this?
public:
void manage_data_in_memory();
protected:
data;
};
class derived : public base
{
public:
void sendData();
private:
virtual void sendDataHelper(); // override this in derived classes which need to send custom data in addition to the default data
};
class derived2 : public base
{
public:
void do_Z_On_data()
};
The destructor of a base class must be virtual if and only if an instance of a derived class will be destroyed through a pointer to the base object. If the destructor isn't virtual in such case, then the behaviour of the program would be undefined. Example:
struct Base {
// ...
};
struct Derived : Base {};
std::unique_ptr<Base> ptr = std::make_unique<Derived>();
// Base::~Base must be virtual
It's possible to prevent the user of the class from doing this (at least by accident) by using private inheritance. If the destructor isn't virtual, then inheritance should be private except possibly in special cases where you need a standard layout class.
is this because private inheritance would make the destructor private
No, private inheritance doesn't make destructor private.
which prevents anyone from declaring an object of Base?
No, and declaring an object of Base isn't a problem.
Private inheritance prevents conversion from derived pointer into a base pointer outside the member functions of the derived class (and friends). The inability acquire a pointer to base of the derived class would prevent the user from deleting a derived object through such pointer.
Note: I am not asking why a parent class need to have virtual method.
I remember something coding guideline like that(I don't remember well and just try to express as my own word,hope I have correct wording): if the parent class have virtual method,the derived class should also at least have one virtual method, even the derived class would not have derived class from itself, if the derived class really no need to have any virtual method, set destructor as virtual. The reason behind it is something like "prevent duplicate virtual table", what is it talking about?
And I also remember a related example like that:
class A{
virtual f();
};
class B : public A{
};
B as no derived class, if B has no virtual method, the consequence is something like "any place that include B will have a duplicate virtual table generated by compiler" (also is just expressed from my impression), what is the meaning of that (if it is true)?
Note the following:
If the base class has a virtual member function other than a destructor, the derived class inherits that function.
If the base class declares a member function as virtual, and the derived class declares a member function of the same name with the same argument types, then the derived class function is automatically virtual, and overrides the base class's function.
If the base class has a virtual destructor, the derived class's destructor is automatically virtual, whether user-declared or not, and overrides the base class's destructor.
The example you gave is not in any way problematic. I would advise you to forget everything you think you remember about this coding standard.
I want to implement an inheritance hierarchy in my C++ game engine that has some analogies from Java:
all objects inherit from Object class,
some functionality is provided by interfaces.
It's just an analogy that gives me some benefits (not a strict 1:1 Java:C++ mapping which is not possible).
By "interface" I mean here a class with only pure virtual, public methods. I know that it's not a strict and precise definition of it.
So I've made:
class Object{...};
/* interfaces */
class Nameable : public Object{...};
class Moveable : public Object{...};
class Moveable3D : public Moveable{...};
class Moveable2D : public Moveable{...};
class Model3D : public Moveable3D, public Nameable{...}
class Line3D : public Moveable3D{...}
class Level: public Nameable{...}
class PathSolver : public Object{...}
As you can see, Model3D now inherits from Object via multiple ways:
Moveable3D -> Moveable -> Object,
Nameable -> Object.
And my compiler in VS2013 (VC++) warns me about it.
Is that an issue?
If so, how to solve it to get a better inheritance structure?
I was thinking about two ways, but both have more disadvantages then advantages:
Dropping the inheritance between e.g. Nameable and Object. But that way Level would lost its inheritance from Object too (and my first goal was: all objects inherit from Object class).
I could also drop : public Object from each interface. But that way I would be force to manually type :public Object in each of many engine final classes (Model3D, Line3D, Level, PathSolver). That way both refactoring and creating new final types would be harder. Moreover the information that each interface will be guaranteed to inherit from Object is lost that way.
I would like to avoid virtual inheritance (one level of abstraction further) if it's not necessary. But maybe it is (at least for : public Object)?
As said by Juraj Blaho the canonical way to solve this problem is virtual inheritance. One implementation model for virtual inheritance is to add an entry in the vtable of classes using virtual inheritance pointing to the real unique object from the base class. That way, you get the following inheritance graph :
Model3D
/ \
Moveable3D Nameable
| |
Moveable |
\ /
Object
That is you must have :
class Nameable : public virtual Object{...};
class Moveable : public virtual Object{...};
The other classes do not need virtual inheritance
Without virtual inheritance the graph would have been
Model3D
/ \
Moveable3D Nameable
| |
Moveable |
| |
Object Object
with 2 distinct instances of Object
The most tricky part in virtual inheritance is the call of constructors (ref Virtual Inheritance in C++, and solving the diamond problem) Because there is only a single instance of a virtual base class that is shared by multiple classes that inherit from it, the constructor for a virtual base class is not called by the class that inherits from it (which is how constructors are called, when each class has its own copy of its parent class) since that would mean the constructor would run multiple times. Instead, the constructor is called by the constructor of the concrete class. ... By the way, the constructors for virtual base classes are always called before the constructors for non-virtual base classes. This ensures that a class inheriting from a virtual base class can be sure the virtual base class is safe to use inside the inheriting class's constructor. The destructor order in a class hierarchy with a virtual base class follows the same rules as the rest of C++: the destructors run in the opposite order of the constructors. In other words, the virtual base class will be the last object destroyed, because it is the first object that is fully constructed.
But the real problem is that this Dreadful Diamond on Derivation is often considered as a bad hierarchy design and is explicitely forbidden in Java.
But IMHO, what C++ virtual inheritance does under the hood is not that far from what you would have if all your interface classes were pure abstract classes (only pure virtual public methods) not inheriting from Object and if all you implementation classes did inherit explicitely from Object. Using it or not is up to you : after all it is part of the language ...
Use virtual inheritance of interfaces. That will ensure that there is only one instance of base class in the derived classes:
class Object{...};
/* interfaces */
class Nameable : public virtual Object{...};
class Moveable : public virtual Object{...};
class Moveable3D : public virtual Moveable{...};
class Moveable2D : public virtual Moveable{...};
class Model3D : public virtual Moveable3D, public virtual Nameable{...}
class Line3D : public virtual Moveable3D{...}
class Level: public virtual Nameable{...}
class PathSolver : public virtual Object{...}
Without virtual inheritance there are multiple instances of the same base in the object which will cause that you will not be able to substitute the concrete type where the interface is needed:
void workWithObject(Object &o);
Model3D model;
workWithObject(model);
Yes, it is an issue: In the memory layout of Model3D, there are two subobjects of type Object; one is a subobject of Movable3D, the other of Nameable. As such, these two subobjects may contain different data. This is especially a problem, if the object class contains functionality that has to do with the identity of an object. For instance, an Object class that implements reference counting must be a unique subobject of all objects; an object that has two different reference counts is very likely a very bad idea...
To avoid this, use virtual inheritance. The only virtual inheritance that is needed is from the Object base class:
class Objec{...];
class Nameable : public virtual Object{...};
class Moveable : public virtual Object{...};
class Moveable3D : public Moveable{...};
class Moveable2D : public Moveable{...};
class Model3D : public Movable3D, public Nameable{...};
...
Virtual inheritance will bring order in your class hierarchy. A few things to watch for:
Don't mix virtual/non-virtual inheritance for the same base class in your hierarchy unless you really know what you are doing.
Initialization order becomes tricky. Constructor of the virtually inherited class will be called only once. The constructor will take arguments from the most derived class. If you don't specify it explicitly in Moveable3D the default constructor will be called, even if Moveable specified arguments for Object's constructor. So, to avoid the mess make sure you use only DEFAULT constructors in all classes you inherit virtually.
First make sure that Model3D ( which is using multiple inheritance ) has to provide interface from both its' base classes i.e Nameable as well as Model3D. Because from the name you have provided to your class it seems to me that Nameable should better be implemented as a member of 'Model3D'.
Apart from that most of issues in multiple inheritance comes if base classes have their own data. Like then you have to decide whether base class would be virtual OR not and etc... However, you mentioned that base classes are all interface i.e with at least one pure virtual function. So, I think you can avoid many problems of multiple inheritance.
#include<iostream>
using namespace std;
class base
{
public:
virtual void f(){}
};
class middle1:public base
{};
class middle2:public base
{};
class derive:public middle1,public middle2
{};
int main()
{
derive* pd=new derive();
pd->f();
return 0;
}
I know that virtual solves this problem, but how?
Can we always write public virtual for safety, even we don't have multiple inheritance.
Each instance of derive has a middle1 base class sub-object and a middle2 base class sub-object.
If the inheritance is non-virtual, then the middle1 base class sub-object has a base base class subobject, and the middle2 base class sub-object also has a base base class sub-object. Hence, each instance of derive has two base sub-objects, and the call pd->f() is ambiguous -- which of the base objects do you want to call f() on?
Making the inheritance virtual means that middle1 and middle2 will share a single base sub-object of derive. This removes the ambiguity -- there is only one base object that f() could be called on.
Can we always write public virtual for safety
Not necessarily. There may be inheritance hierarchies in which you don't want middle1 and middle2 to share a public base sub-object. You could probably argue that in such cases, you shouldn't be writing a class derive that inherits from both, but if you do end up with that situation then the workaround would be to do either:
static_cast<middle1*>(pd)->f();
pd->middle1::f();
to specify that you want to call f on the middle1 base class sub-object, or
static_cast<middle2*>(pd)->f();
pd->middle2::f();
to specify middle2.
Virtual base classes implement an additional indirection level in order to solve the diamond problem (see this question).
If you always use virtual inheritance, you will always suffer the performance penalty resulting from that additional indirection level.
Therefore, I would suggest you only use virtual inheritance when you have to.
I know that virtual solves this problem, but how?
virtual keywords solves the problem by making only one top order base class subobject to be present in the inheritance hierarchy. Without it each parent class middle1 & middle2 have their own copy of the base class thus resulting in ambiguity.
Can we always write public virtual for safety, even we don't have multiple inheritance.
There is no reason to use virtual inheritance if you don't have multiple inheritance. Multiple inheritance is the purpose for concept of virtual inheritance to exist.
I am a freshman in C++, especially about object-oriented programming. And now I have a problem during my learning.
There is a class hierarchy following:
class Class{};
class Base:public Class{};
class Derived1:virtual public Base{};
class Derived2:virtual public Base{};
class MI:public Derived1,public Derived2{};
class Final:public MI,public Class{};
And now I want to know what the order of constructor for the definition of a Final class object is.
I draw a diagram:
structure of class inheritance http://hi.csdn.net/attachment/201203/16/2712336_1331902452BziD.jpg
I know Virtual base classes are always constructed prior to nonvirtual base classes regardless of where they appear in the inheritance hierarchy. What I am confused is that if constructor of class Class is before Base, and if constructor of Class is invoked twice. And why?
Can someone tell my the answer? The more detailed, the better.
The direct inheritance of Class by Final and Base is not virtual, so an instance of Final has two base class subobjects of type Class. The one that is the direct base of Base is constructed before Base, and the one that is the direct base of Final is constructed afterwards (in fact after MI).
The reason is that:
direct bases are constructed in the order they're listed (unless they're a virtual base that has been constructed already),
bases are constructed before the class's own constructor runs.
Applying (1) to Final tells us that Class is constructed after MI. Applying (2) several times tells us that Class is constructed before Base, before Derived1 and Derived2, before MI.