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
Related
I face the well known "dreaded" diamond situation :
A
/ \
B1 B2
\ /
C
|
D
The class A has, say the constructor A::A(int i). I also want to forbid a default instantiation of a A so I declare the default constructor of A as private.
The classes B1 and B2 are virtually derived from A and have some constructors and a protected default constructor.
[edit]
The constructors of B1 and B2 don't call the default constructor of A.
[reedit]
The default constructors of B1 and B2 don't call the default constructor of A either.
[reedit]
[edit]
The class C is an abstract class and has some constructors that don't call any of the A, B1 or B2 constructors.
In the class D, I call the constructor A::A(i) and some constructor of C.
So as expected, when D is created, it first creates a A to solve the dreaded diamond problem, then it creates B1, B2 and C. Therefore there is no call of the default constructor of A in B1, B2 and C because if there was, it would create many instances of A.
The compiler rejects the code because the default constructor of A is private. If I set it to protected it compiles.
What I don't understand is that when I run the code, the default constructor of A is never called (as it should be). So why doesn't the compiler allow me to set it as private?
[edit]
okay I'll write an example... but it hurts ;-)
class A{
public:
A(int i):i_(i){};
virtual ~A(){};
protected:
int i_;
private:
A():i_(0){};/*if private => compilation error, if protected => ok*/
};
class B1: public virtual A{
public:
B1(int i):A(i){};
virtual ~B1(){};
protected:
B1():A(0){};
};
class B2: public virtual A{
public:
B2(int i):A(i){};
virtual ~B2(){};
protected:
B2():A(0){};
};
class C: public B1, public B2{
public:
C(int j):j_(j){};
virtual ~C()=0;
protected:
int j_;
};
C::~C(){};
class D: public C{
public:
D(int i,int j):A(i),C(j){};
~D(){};
};
int main(){
D d(1,2);
}
The compiler says that in constructor of C, A::A() is private. I agree with this, but as C is an abstract class, it can't be instantiated as a complete object (but it can be instantiated as a base class subobject, by instantiating a D).
[edit]
I added the tag `language-lawer' on someone's recommendation.
C++ doesn't have an access control specifier for member functions that can only be called from a derived class, but a constructor for an abstract class can only be called from a derived class by definition of an abstract class.
The compiler cannot know in advance exactly which classes are instantiated (this is a runtime property), and it cannot know which constructors are potentially called before link-time.
The standard text (emphasis mine):
All sub-objects representing virtual base classes are initialized by
the constructor of the most derived class (1.8 [intro.object]). 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.
1) It makes no exception for abstract classes and can only be interpreted as saying that all constructors should do a (sometimes fake) attempt at calling virtual base constructors.
2) It says that at runtime such attempts are ignored.
Some committee members have stated a different opinion in DR 257:
Abstract base constructors and virtual base initialization
Section: 12.6.2 [class.base.init] Status: CD2 Submitter: Mike
Miller Date: 1 Nov 2000 [Voted into WP at October, 2009 meeting.]
Must a constructor for an abstract base class provide a
mem-initializer for each virtual base class from which it is directly
or indirectly derived? Since the initialization of virtual base
classes is performed by the most-derived class, and since an abstract
base class can never be the most-derived class, there would seem to be
no reason to require constructors for abstract base classes to
initialize virtual base classes.
It is not clear from the Standard whether there actually is such a
requirement or not. The relevant text is found in 12.6.2
[class.base.init] paragraph 6:
(...quoted above)
This paragraph requires only that the most-derived class's constructor
have a mem-initializer for virtual base classes. Should the silence be
construed as permission for constructors of classes that are not the
most-derived to omit such mem-initializers?
There is no "silence". The general rule applies as there is no specific rule for abstract classes.
Christopher Lester, on comp.std.c++, March 19, 2004: If any of you
reading this posting happen to be members of the above working group,
I would like to encourage you to review the suggestion contained
therein, as it seems to me that the final tenor of the submission is
both (a) correct (the silence of the standard DOES mandate the
omission) and (b) describes what most users would intuitively expect
and desire from the C++ language as well.
The suggestion is to make it clearer that constructors for abstract
base classes should not be required to provide initialisers for any
virtual base classes they contain (as only the most-derived class has
the job of initialising virtual base classes, and an abstract base
class cannot possibly be a most-derived class).
The suggestion cannot make "clearer" something that doesn't exist now.
Some committee members are taken their desire for reality and it is very wrong.
(snip example and discussion similar to OP's code)
Proposed resolution (July, 2009):
Add the indicated text (moved from paragraph 11) to the end of 12.6.2
[class.base.init] paragraph 7:
...The initialization of each base and member constitutes a
full-expression. Any expression in a mem-initializer is evaluated as
part of the full-expression that performs the initialization. A
mem-initializer where the mem-initializer-id names a virtual base
class is ignored during execution of a constructor of any class that
is not the most derived class.
Change 12.6.2 [class.base.init]
paragraph 8 as follows:
If a given non-static data member or base class is not named by a
mem-initializer-id (including the case where there is no
mem-initializer-list because the constructor has no ctor-initializer)
and the entity is not a virtual base class of an abstract class (10.4
[class.abstract]), then
if the entity is a non-static data member that has a
brace-or-equal-initializer, the entity is initialized as specified in
8.5 [dcl.init];
otherwise, if the entity is a variant member (9.5 [class.union]), no
initialization is performed;
otherwise, the entity is default-initialized (8.5 [dcl.init]).
[Note: An abstract class (10.4 [class.abstract]) is never a most
derived class, thus its constructors never initialize virtual base
classes, therefore the corresponding mem-initializers may be omitted.
—end note] After the call to a constructor for class X has
completed...
Change 12.6.2 [class.base.init] paragraph 10 as follows:
Initialization shall proceed proceeds in the following order:
First, and only for the constructor of the most derived class as
described below (1.8 [intro.object]), virtual base classes shall be
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 class
names in the derived class base-specifier-list.
Then, direct base classes shall be are initialized in declaration
order as they appear in the base-specifier-list (regardless of the
order of the mem-initializers).
Then, non-static data members shall be are initialized in the order
they were declared in the class definition (again regardless of the
order of the mem-initializers).
Finally, the compound-statement of the constructor body is executed.
[Note: the declaration order is mandated to ensure that base and
member subobjects are destroyed in the reverse order of
initialization. —end note]
Remove all normative text in 12.6.2 [class.base.init] paragraph 11,
keeping the example:
All subobjects representing virtual base classes are initialized by
the constructor of the most derived class (1.8 [intro.object]). 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. [Example:...
The DR is marked "CD2": the committee agrees this was an issue and the language definition is changed to fix this issue.
This question already has answers here:
Order of calling constructors/destructors in inheritance
(6 answers)
Closed 9 years ago.
I have a class structure of three classes where two of them are base classes of the third, like this:
class A {
};
class B {
};
class C : public A, public B {
};
When an instance of C is to be destroyed, in which order are the base classes A and B destroyed? Are there any rules for this?
There are rules (C++11 §12.4):
After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data members, the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes. All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual overriding destructors in more derived classes. Bases and members are destroyed in the reverse order of the completion of their constructor (see 12.6.2). A return statement (6.6.3) in a destructor might not directly return to the caller; before transferring control to the caller, the destructors for the members and bases are called. Destructors for elements of an array are called in reverse order of their construction (see 12.6).
The construction order is (§12.6.2/10):
In a non-delegating constructor, initialization proceeds in the following order:
— First, and only for the constructor of the most derived class (1.8), 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).
— Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
— Finally, the compound-statement of the constructor body is executed.
[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the
reverse order of initialization. — end note ]
So in simple cases, base constructors are called in the order in which the classes are listed in the declaration, and destructors run in reverse of that order.
According to c++ rules, when defining a derived class object, the base class constructor is called to initialize the base class members and then the derived class constructor. For the destructor, the rule reverts.
I'm wondering why this rule should be obeyed. Why first base constructor and then derived class constructor? Is there any reason for doing this? or just because it's the definition of c++.
Thanks,
because members of the derived class may depend on members of the base class, members of the base class have to be initialized first.
You can't argue the opposite.
An object of class type consists of subobjects - its base class subobjects and (non-static) data members.
Before a subobject is constructed, in its place is raw uninitialized storage, which you must not use as an object.
The subobjects of an object are constructed before the body of the constructor for the object is entered, so that you can use these subobjects in the constructor body.
That base class subobjects are constructed before member subobjects is just a rule, but may be motivated by the following observations:
A derived object is a base object and adds additional members and behaviors. It seems natural to first construct the base part on which the derived part rests, before adding the new parts.
When the base class subobject is constructed, you can use it (except for polymorphic behavior) through it regular interfaces, including in the initialization of data members. The converse is not true: you can't access derived class members the regular way (through encapsulating member functions) until the derived object is fully constructed (which includes the base class subobjects.
A technical reason for this construction order is that compilers typically initialize the data needed for polymorphism (vtable pointers) in constructors. So first a base class constructor initializes this for its class, then the derived class constructor overwrites this data for the derived class. This also corresponds to the rules for behavior of polymorphic functions in constructors.
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.
virtual and inline are function specifier.
They can appear before function only.{as per my understanding}.
Then,In following code what is virtual?
class Base
{
//
};
class Derived :virtual public Base
{
};
This is virtual inheritance.
If your question is about the wording in the standard, then you must have misunderstood it. It is true that the list of various function specifiers includes the keyword virtual as one possible function specifier. However, it doesn't work in other direction: the keyword virtual is not restricted to being the function specifier only. It has other use(s). You have found an example of that - it can be used to declare virtual base classes.
$10.1/4- "A base class specifier that
contains the keyword virtual,
specifies a virtual base class. For
each distinct occurrence of a
nonvirtual base class in the class
lattice of the most derived class, the
most derived object (1.8) shall
contain a corresponding distinct base
class subobject of that type. For each
distinct base class that is specified
virtual, the most derived object shall
contain a single base class subobject
of that type."
So given the hierarchy
struct A{};
struct B : virtual A{};
struct C : virtual A{};
struct D : B, C{};
D d;
A 'd' object has only one 'A' subobject i.e. the constructor of 'A' is called only once, and that too before any other constructor is run.
$12.6.2/5 - "Initialization shall
proceed in the following order:
—
First, and only for the constructor of
the most derived class as described
below, virtual base classes shallbe
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. [Note: the declaration
order is mandated to ensure that base
and member subobjects are destroyed in
the reverse order of initialization. ]
It is virtual inheritance, look here for an explanation.
The common usage is, if you have a class A inheriting from 2 classes B and C, which in turn inherit from the same ancestor D. This is problematic with normal inheritance, since A would contain two instances of D, so which one should be used. Using virtual inheritance, e.g. C inheriting virtual from D, the address of the D instance in the C-part of A is found in the vmt, so it can point to the same instance that the B-part is using
virtual inheritence its used to specify how inheritence works when there is multiple inheritence. essentially it allows you to have 'diamond' inhertitence graphs as opposed to non virtual which would give you a tree, with multiple bases clases at the leaves (raising potenetial ambiguity problems).