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.
Related
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.
Are multiple-inherited constructors called multiple times? And in what order are constructors called? Does this depend on the order in the inheritance list?
Here is an example (it's only for making the situation clear, no real-life example).
class Base {};
class DerivedBaseOne : public Base {};
class DerivedBaseTwo : public Base {};
class Derived : public DerivedBaseTwo, public DerivedBaseOne
{};
//somewhere in the code, is Base() called two times here?
Derived * foo = new Derived();
Is the Base() constructor called twice? And in what order are the constructors called? Base first? Or DerivedBaseOne() or DerivedBaseTwo() first?
The order of constructor calls for your inheritance hierarchy will be:
Base()
DerivedBaseTwo()
Base()
DerivedBaseOne()
Derived()
The order is indeed well-defined and depends on the order in which you mention the derivation for base classes and the order in which you declare members in the class for members. (See the reference from the C++ Standard below.)
Does the Base() constructor get called twice?
YES
The Base() class constructor gets called here twice, because two classes DerivedBaseTwo() and DerivedBaseOne() derive from it, so the base class constructor gets called once for each of them. Your Derived class has two distinct Base subobjects through multiple paths (one through DerivedBaseOne() and the other though DerivedBaseTwo()).
The hierarchy of classes you have with multiple inheritance is unusual and it leads to a problem called the Diamond Shaped Inheritance Problem. To avoid this problem C++ introduces the concept of Virtual base class.
Reference:
C++03 Standard: 12.6.2/5, Initializing bases and members
Initialization shall proceed in the following order:
— First, and only for the constructor of the most derived class as described below, virtual base classes shall be 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 class names in the derived class base-specifier-list.
— Then, direct base classes shall be initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
— Then, nonstatic data members shall be initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
— Finally, the body of the constructor is executed.
The way you write it, Derived has two distinct subobjects of type Base, and each gets their own constructor called from the respective DerivedBaseXXX constructor of which it is the subobject. The order of calls follows the order of declaration.
By contrast, of you declare DerivedBaseXXX : virtual public Base, then there is only one Base subobject, and its constructor is called from the most derived object, i.e. from the Derived object.
(To explain in a bit more detail: A (possibly singly-inheriting) class is constructed by first 1) calling the base class's constructor, then 2) calling the constructors of all member objects in their order of declaration, and finally 3) executing the constructor function body. This applies recursively, and for multiple inheritance, you just replace (1) by calling all the base class's constructors in the order in which the inheritance was declared. Only virtual inheritance adds a genuine extra layer of complication here.)
This is answered in: http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.14
The very first constructors to be executed are the virtual base classes anywhere in the hierarchy. They are executed in the order they appear in a depth-first left-to-right traversal of the graph of base classes, where left to right refer to the order of appearance of base class names.
Since your multiple inheritance declaration lists DerivedBaseTwo first, its construction order will be executed before DerivedBaseOne's.
So in your Derived class, DerivedBaseTwo and its chain is created first, that is:
1 - Base then DerivedBaseTwo
And then DerivedBaseOne and its chain:
2 - Base then DerivedBaseOne
And then:
3 - Derived is created after everything else.
Also, with multiple inheritance be mindful of the Diamond Inheritance Problem
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.
class base {};
class der1 : public base{};
class der2 : public base{};
..........
..........
class derXXX : public base{};
Several class have been derived from base.
existing code: base class is not abstract class, so there are instance of base class alongwith all derive class.All the testing have been done.
Requirement:Now I want to stop instance creation of base class without any changing /testing of all derive class. How it can be done?
One option would be tom make every constructor of Base protected, so they can only be accessed by derived classes and the class itself. This would prevent instantiation of the object by itself but permit the instantiation of base classes.
If the base class does not have a constructor, then just declare a new, empty constructor that takes no arguments. Also be sure to provide an implementation of the copy constructor (or leave it unimplemented and private) so that the automatically-generated copy constructor is not left publicly visible.
Make all of the base class constructors (including the default constructor and copy constructor) private or protected.