C++ virtual inheritance initializer list - c++

in the following code:
class A
{
public:
int x;
A(int x):x(x){}
};
class B: public virtual A
{
public:
B(int x):A(x){}
};
class C: public virtual A
{
public:
C(int x):A(x){}
};
class D: public B, public C
{
public:
D(int x):B(x++), C(x++), A(x++){}
};
two questions:
Why do I need to add A(...) in D's initializer list?
D(int x):B(x++), C(x++), A(x++){} and D(int x):A(x++), B(x++), C(x++){} both give the same result with cout<<D(10).x, why?

Why do I need to add A(...) in D's initializer list?
That's because virtual base subobjects must be initialized before all other subobjects. Since A does not have a default constructor, you need to initialize the virtual A subobject in D explicitly and specify which argument you want it to be constructed with.
When the constructors of the B and C base subobjects are executed, they won't have a base A subobject to initialize (that has been done before already). Therefore, the arguments they pass to A's constructor are irrelevant.
D(int x):B(x++), C(x++), A(x++){} and D(int x):A(x++), B(x++), C(x++){} both give the same result with cout<<D(10).x, why?
As explained above, that's because virtual base subobjects are initialized first anyway.
In general, the order of initialization of a class's subobjects never depends on the order in which they appear in your constructor's initialization list. Per paragraph 12.6.2/10 of the C++11 Standard:
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.

Virtual base classes are only initialised by the most-derived class. That is, if create an instance of D in your example, A will only be initialised by its occurence in the mem-initialiser list of D. Its occurence in the mem-initialiser lists of B and C is simply ignored.
That is also why you have to initialise A in D: A doesn't have a default ctor, so D must know how to initialise it.

Related

C++: default constructor implementation

I have a class which inherits from a base class which provides a protected constructor which is empty.
Is it necessary for me to implement the blank constructor (and destructor) in the derived class or will the compiler generate the appropriate one for me. I am using C++ 11.
While some aspacts of the questions are answered in this post (How is "=default" different from "{}" for default constructor and destructor?), I am mostly interested in the behaviour when the class is derived.
So I have something like:
template<typename EnumClass>
class IVCounter
{
protected:
//!
//! \brief Ensure that this base class is never instantiated
//! directly.
//!
IVCounter() {}
public:
//!
//! \brief Virtual destructor
//!
virtual ~IVCounter() {}
};
class Derived: public IVCounter<SomeType>
{
// Do I have to do this?
Derived()
: IVCounter()
{}
~Derived() {}
};
Or perhaps in the derived I can simply do:
Derived() = default;
~Derived() = default;
or maybe even leave it out altogether?
You do not need an explicit constructor here. The implicit default constructor is enough. Draft N4659 says at
15.6.2 Initializing bases and members [class.base.init] § 13:
In a non-delegating constructor, initialization proceeds in the following order:
First, and only for the constructor of the most derived class (4.5), 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.
The implicitely default constructor has just an empty body, but construction of an object implies construction of its base classes
Yes. compiler will generate blank constructor, you need not.
Default generated constructor would be public, so following is enough
class Derived: public IVCounter<SomeType>
{
};

In an abstract class constructor, why I do need to call a constructor of a virtual base that will never to called?

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.

inheriting constructors of class virtually derived.

I came across this question which asks its output.
#include<iostream>
using namespace std;
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;
}
There are few things which I did not understand.
Please clarify these doubts.I could not google it as I did not know what to search for.
Q1. As in the code a parameterised constructor is used.Just after the colon(:) we write the constructor of the parent class.How
A(int j=3):i(j){}
is used? As i is not a class.
Q2. In the class D, the constructor for the class is using the constructors for initialising the base classes.But as it can be seen that all the constructors modify variable i of the class A only.
Then what is the sequence of the constructor calling here.
I know when we do not call the constructor of the parent class, it is explicitly called and the order is well known, but what when we implicitly call the constructor like here.
Q3. Inspite of the parameters being initialized, the value which we send in the constructor seems to make a difference.Why is it so ?
A1. :i(j) in A(int j=3):i(j){} is an initializer list. Initializer lists can specify how parent classes and member variables are initialized. (j) is the initializer for i and behaves similarly to initialization for a local variable: int i(j);. (you may be more familiar with the initialization syntax int i = j; which is similar. You can't use the = syntax in initializer lists.)
A2. Virtual base classes are always initialized exclusively by the most derived class's constructor. So D's constructor initializes its A base class and when D's constructor calls the constructors for B and C those constructors do not reinitialize A.
A3. The syntax D(int j=0) does not initialize the parameter. Instead it declares a default value for the parameter which is ignored whenever you explicitly pass a value for that parameter.
The ctor-initializer-list contains the initializers for all subobjects. That means base class subobjects and member subobjects.
Subobjects are initialized in the order in which they appear in the class definition, always. it doesn't matter what order you put them in the ctor-initializer-list (although putting them in any other order is confusing when the order is ignored).
Inherited base subobject constructors are called by the constructor of the class which is directly derived... except for virtual base subobjects, which are called directly from the constructor for the most-derived object. Virtual base subobjects are constructed before anything else.
There's no such thing as "parameters being initialized". Those are default arguments, and they are ignored when an actual argument is provided.
1) The colon : can be used in a constructor to call the constructors of member variables with the given arguments:
public:
int i;
A(int j=3):i(j){}
means that A's member i will call its constructor with j as the argument.
2) Subobjects will be initialized in the order they appear in the class definition
class D:public B, public C
3) They weren't initialized, they were given default arguments.
Q1:
That code in the constructor between the signature of the function and before the opening bracket of the function body is called an initializer list.
The syntax of an initializer list is a listing of member variables of the class with corresponding initial values. The initial values are in parenthesis. The member variables are separate by comma's. The first variable comes after a colon.
An initializer list can also include a constructor to base class, which is what your B and C class do. Your 'A' class simply uses the form that initializes a member variable.
Q2:
To find the order that the constructors are executed in, put in some print statements. It will help you understand the order of construction. Also put in a destructor and put print statements in those too. I can't do all of your homework for you on this question. :)
Q3:
I guess by parameters being initialized you mean the default arguments? Default arguments are always always overridden if a value is actually passed into the function.

Class component order of initialisation

class D: A
{
B obj;
C obj2;
}
What order of construction here is guaranteed?
I know that D will be constructed after A, B and C, but what I really want to know is whether A is guaranteed to be constructed before B or C, or even whether B is guaranteed to be constructed before C.
I know you can have an explicit initialiser list:
D(): A(), B(), C()
{}
but does that initialiser list determine the order of initialisation?
Also, does whether or not any of the components do or don't have a default constructor?
From the C++03 standard ISO/IEC 14882:2003(E) §12.6.2/5 [class.base.init]:
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.
[Note: the declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. ]
So in this case, you are guaranteed that the order of initialization will be first the base class A, then the subobject B (since it appears first in the list of class members in the class definition), then the subobject C. The order of the initializer list is irrelevant, as is whether or not any of the members do or do not have a default constructor—if a member does not have a default constructor and it is not explicitly initialized in an initializer list, then it has an unspecified value.
but does that initialiser list determinethe ORDER of initialisation?
No. Initialization-list doesn't determine the the order of initialization of member data and the base subobject(s). Members are initialized in order of their declaration, and base subobjects are constructed in the order of their mention - from left to right:
struct A : B, C {} //B is constructed before C
Also, the base subobjects are constructed before the initialization of the member data.
struct A : B, C
{
D d;
E e;
};
Order of initialization in the above struct:
B => C => d => e
subobject subobject member member
And they're destructed in the reverse order.
Perhaps this example of broken code will help illustrate:
If I define a class like so:
class Connection {
boost::asio::tcp::ip::socket _socket;
boost::asio::io_service _io_service;
Connection() : _io_service(), _socket(_io_service)
{
}
};
This will fail in all modern compilers. Because _socket is defined first as a class member, the initialization list will try to initialize it first, despite the fact that the initialization list asks the compiler to initialize _io_service first. But since _io_service has not yet been initialized (the socket constructor depends on an initialized _io_service), the initialization of _socket will cause a segfault.
Perhaps somebody can quote the appropriate section of the standard that dictates this behaviour.
For the second half of the question, base classes will always be initialized before the classes own members.

Function specifier

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).