Are the C++ member classes constructed before parent classes? [duplicate] - c++

This question already has answers here:
C++: Construction and initialization order guarantees
(5 answers)
Closed 8 years ago.
In the scenario:
class A : public B {
private:
C m_C;
public:
A();
}
is
A::A() :
m_C(5),
B(m_C)
{}
legal? Would B::B(m_C) be invoked after C::C(int)? If so, what should I do to avoid it?
How did this came about in practice:
class MyValidator : public QRegExpValidator {
private:
QRegExp myRegExp;
public:
MyValidator();
virtual void fixup(QString &f);
}
MyValidator::MyValidator()
QRegExpValidator(QRegExp("foo"));
{}
void MyValidator::fixup(QString &f){
// A QRegExp("foo") is also needed here.
}
I already discovered the
const QRegExp & QRegExpValidator::regExp() const;
Which alleviates the need to keep my own reference to myRegExp, so my particular problem is solved..
what remains, is what would be the best pattern if QRegExpValidator did not have such feature to retrieve it's initializer.. manually plumbing all the functions to a member class, instead of inheritance?

This is what the C++11 Standard has to say ([class.base.init]/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, the base class is initialized before non-static data members. Your code may invoke undefined behavior if it actually uses the uninitialized data in any way.
In comments, we discussed one possible solution to your design problem is to use has-a rather than is-a. You worried that has-a would violate DRY (don't repeat yourself).
There are two ways I use to avoid WET (write everything (at least) twice) when using has-a. One is using conversion operators that allow your object to be passed to a function expecting your "derived" type. The other is using a delegation operator.
class Object { /* ... */ };
class FakeDerivedObject {
Foo foo;
Object obj;
//...
// conversions
operator Object & () { return obj; }
operator const Object & () const { return obj; }
operator Object * () { return &obj; }
operator const Object * () const { return &obj; }
// delegation
Object * operator -> () { return &obj; }
const Object * operator -> () const { return &obj; }
};
This way, you do not have to "re-implement" the interface of the underlying object.
FakeDerivedObject d;
d->SomeMethodOfUnderlyingObject();
SomeFunctionThatExpectsUnderlyingObject(d);

Is
A::A() : m_C(5), B(m_C) {}
legal?
Yes. You can list initializers in any order you choose.
Would B::B(m_C) be invoked after C::C(int)
No. The compiler will ignore the order you listed the initializers, and initialize bases first in the order they are listed in the class declaration, followed by members in the order they are declared in the class declaration.
Note that most compilers have a warning level which will warn you when initializers are listed in an order other than that matching how the initializers will actually be invoked. According to some coding standards, it is required to list the initializers in the order in which they will be invoked.

Example:
class Base {
public:
Base(){}
};
class Derived: public Base {
public:
Derived();
private:
int _v1;
int _v2;
};
The construction order will be ever Base --> _v1 --> _v2

Related

Why did the creator of C++ decide to use constructor initializer list to initialize base classes?

Why did the creator of C++ decide to use constructor initializer list to initialize base classes? Why didn't he instead choose to use syntax like the second comment line in the following code?
class A{
public:
A() { }
};
class B : A{
public:
B() : A() { } // Why decide to use this one, using constructor initializer, to initialize base class?
B() { A(); } // Why not choose this one? It's easy for me to understand if it was possible.
};
int main(int argc, char *argv[]){
/* do nothing */
}
The advantage of using an initializer list is, that you have a completely initialized object in the body of the constructor.
class A {
public:
A(const int val) : val(val) { }
private:
const int val;
};
class B : A{
public:
B() : A(123) {
// here A and B are already initialized
}
};
So you have a guarantee that all members, even those of the parent, are not in an undefined state.
Edit
In the example of the question it is not necessary to call the base class in the initializer list, this is done automatically. So I slightly modified the example.
I can see a few possible alternatives to the current C++ rule that base classes and data members of a class type are initialised in the mem-initialiser list of the class type's constructor(s). They all come with their set of issues, which I will discuss below.
But first, note that you cannot simply write a derived constructor like this:
struct Derived : Base
{
Derived()
{
Base(42);
}
};
and expect the line Base(42); to call the base class constructor. Everywhere else in C++, such a statement creates a temporary object of type Base initialised with 42. Changing its meaning inside a constructor (or just inside its first line?) would be a syntax nightmare.
Which means that new syntax would need to be introduced for this. In the rest of this answer, I will use a hypothetical construct __super<Base> for this.
Now on to discuss possible approaches which would be closer to your desired syntax, and present their problems.
Variant A
Base classes are initialised in the constructor body, while data members are still initialised in the mem-initialiser list. (This follows the letter of your question the closest).
The would have the immediate problem of stuff executing in different order than it's written. For very good reasons, the rule in C++ is that base class subobjects are initialised before any data members of the derived class. Imagine this use case:
struct Base
{
int m;
Base(int a) : m(a) {}
};
struct Derived
{
int x;
Derived() :
x(42)
{
__super<Base>(x);
}
};
Written like this, you could easily assume x would be initialised first and then Base would be initialised with 42. However, that would not be the case and instead reading x would be undefined.
Variant B
Mem-initialiser lists are removed altogether, base classes are initialised using __super, and data members are simply assigned in the constructor body (pretty much the way Java does it).
This cannot work in C++ because initialisation and assignment are fundamentally different concepts. There are types where the two operations do vastly different things (e.g. references), and types which are not assignable at all (e.g. std::mutex).
How would this approach deal with a situtation like this?
struct Base
{
int m;
Base(int a) : { m = a; }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x); // This one's OK
r = *pd; // PROBLEM
}
};
Consider the line marked // PROBLEM. Either it means what it normally does in C++ (in which case it assigns a double into a "random place" which the uninitialised reference r references), or we change its semantics in constructors (or just in initial parts of a constructor?) to do initialisation instead of assignment. The former gives us a buggy program while the latter introduces totally chaotic syntax and unreadable code.
Variant C
Like B above, but introduce special syntax for initialising a data member in the constructor body (like we did with __super). Something like __init_mem:
struct Base
{
int m;
Base(int a) : { __init_mem(m, a); }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x);
__init_mem(r, *pd);
}
};
Now, the question is, what have we achieved? Previously, we had the mem-initialiser list, a special syntax to initialise bases and members. It had the advantage that it made clear these things happen first, before the constructor body starts. Now, we have a special syntax to initialise bases and members, and we need to force the programmer to put it at the start of the constructor.
Note that Java can get away with not having a mem-initialiser list for several reasons which don't apply to C++:
The syntax for creating an object is always new Type(args) in Java, whereas Type(args) can be used in C++ to construct objects by value.
Java only uses pointers, where initialisation and assignment are equivalent. For many C++ types, there operations are distinct.
Java classes can only have one base class, so using just super is enough. C++ would need to differentiate which base class you're referring to.
B() : A() { }
This will initialize the base class in user defined way.
B() { A(); }
This will NOT initialize the base class in user defined way.
This will create an object inside of constructor i.e B(){}
I think first initialization has better readability compared to the second and you can also deduce class hierarchy.

Why isn't the noexcept specifier scoped within the declared method?

Trying to design some exception-free classes, I have an inheritance structure similar to this, but I have found the noexcept specifier to be of little to no help when working with member functions as the specifier is not scoped as being within the function.
class Base
{
protected:
Base() noexcept {}
};
class Derived : public Base
{
public:
// error: 'Base::Base()' is protected
Derived() noexcept(noexcept(Base{})) : Base{} {}
// error: 'foo' was not declared in this scope
Derived(int) noexcept(noexcept(foo())) {}
// error: invalid use of 'this' at top level
Derived(float) noexcept(noexcept(this->foo())) {}
void foo() noexcept {}
};
Demo
Is this perhaps something that is being improved in C++17? Trying to search for this has yielded no relevant results. For now I've resigned to some very ugly (and possibly incorrect) attempts such as noexcept(noexcept(static_cast<Derived*>(nullptr)->foo())), but this doesn't assist in the case of the base class constructor, which is protected.
Is it even currently possible to declare a noexcept specifier which references a protected base class method like this? noexcept(auto) might be relevant, but of course isn't possible yet. Have I overlooked anything else that would allow me to include this specifier, or do I simply have to omit it in that case?
You can work around it by using an expression where the Base constructor is in scope like this:
struct test_base : public Base {};
Derived() noexcept(noexcept(test_base())) : Base() {}
I believe the reason you cannot use Base() directly is related to this question.
The way protected access specifier works, it allows the derived class
B to access the contents of an object of base class A only when that
object of class A is a subobject of class B. That means that the only
thing you can do in your code is to access the contents of A through
B: you can access the members of A through a pointer of type B * (or a
reference of type B &). But you cannot access the same members through
a pointer of type A * (or reference A &).
It's the same as if you had a member function like this:
void badfunc()
{
B b;
}
You're trying to use Base's constructor directly instead of going through Derived. When you initialize the base in the constructor initialization list, that is a special context that allows you to call the constructor because you're doing it as part of initializing Derived.
This is really multiple questions in one.
About this...
From my understanding, the use of this is supposed to be completely superfluous but compiler support for C++11 is not entirely universal. This should work, according to the C++11 standard:
struct Base {
void func() noexcept;
};
struct Derived() {
void func() noexcept(noexcept(Base::func())) {}
};
Note that base_func() is a non-static member function, but because it appears in an "unevaluated operand" it is okay. From n3337 sec 4.1.1:
An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
...
if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
However, some compilers do not support this. You are then forced to use std::declval:
#include <utility>
struct Base {
void func() noexcept;
};
struct Derived() {
void func() noexcept(noexcept(std::declval<Base>().func())) {}
};
About accessibility...
I read through the relevant parts of the standard about "unevaluated operands" and "member access control" and I have come to the conclusion that the standard is a bit ambiguous. It mentions that a protected name can be used only by members, friends, and derived classes. The question is whether unevaluated operands "use" the member names which appear in them. They certainly don't odr-use the member names, and can even use member names if no definition is provided, and this kind of ambiguity is exactly why the term "odr-use" even exists! For example,
int f(); // No definition anywhere in program
int x = sizeof(f()); // Completely valid, even without definition of f
struct X {
X() = delete; // Cannot use this constructor
};
int xsize = sizeof(X{}); // Completely valid
Even though it is somewhat unclear, I have a hard time imagining that the C++ committee could have intended to let you use deleted member functions in unevaluated operands but not inaccessible member functions. However, I am not certain.
Note that the above code compiles without error both with GCC and Clang. However, the following code is does not:
class X {
X(){}
};
class Y {
Y() = delete;
};
bool xokay = noexcept(X{}); // Error!
bool yokay = noexcept(Y{}); // Ok
Both GCC and Clang accept Y but not X, which seems a bit weird to say the least. The following code is accepted by Clang but not GCC, and using std::declval does not help:
class Base {
protected:
void func();
};
class Derived : public Base {
// Clang accepts this, GCC does not.
void func2() noexcept(noexcept(Base::func())) {}
};
What a mess.
Conclusions
The conclusion here is that it seems that there is plenty of inconsistency to go around, and plenty of gaps between current compilers and the C++11 specs.

Is it possible to run member initializers before base-class constructor?

Normally one can change the order in which member initializers run by changing the order in which the members are declared in the class. However, is there a way to get the base class initializer/constructor to not run first?
This is a minimal sketch of my problem:
class SpecialA : public A {
public:
explicit SpecialA(Arg* arg)
: member(expensiveFunction(arg))
, A(member) // <-- This will run first but I don't want it to
{}
private:
T member;
}
No, it is not possible. Class initialization is always like that: base class, members, this class constructor.
The reason for this is simple - since you can reference your members in this class constructor, you have to construct members before you call your constructor. Since you can reference your base class members from your members, you have to have them constructed before this class members.
Is it possible to run member initializers before base-class constructor?
Not as such.
That said, here are a few solutions:
1: move the member to an artificial base:
template<typename T>
class InitializerBase {
protected:
InitializerBase(T&& value) : member(std::move(value)) {}
T member;
};
class SpecialA: public InitializerBase<T>, public A {
public:
SpecialA(Arg *arg) : InitializerBase<T>(expensiveFunction(arg)): A{}
{
}
};
(Probably) the best solution would look like this:
2: use dependency injection for the fully constructed value (this is safest, best design and unless your code has bigger problems, most efficient implementation):
class SpecialA : public A {
public:
explicit SpecialA(T fully_computed_value)
: A(fully_computed_value)
, member(std::move(fully_computed_value)) // no heavy computations performed
{}
private:
T member;
}
Construction:
auto &a = SpecialA(expensiveFunction(arg));
This is the best solution because if expensiveFunction throws, you do not even start constructing the resulting object (the application doesn't have to release the resources for the half-constructed SpecialA).
Edit:That said, if you want to hide the use of the expensive function, the canonical solution to that (canonical because it is reusable, minimalistic and still respects good design) is to add a factory function:
SpecialA make_special(Arg *arg)
{
auto result = expensiveFunction(arg);
// extra steps for creation should go here (validation of the result for example)
return SpecialA( std::move(result) );
}
client code:
auto specialA = make_special(arg); // simplistic to call (almost as simple
// as calling the constructor directly);
// hides the use of the expensive function
// and provides max. reusability (if you
// need to construct a SpecialA without
// calling the expensive function, you
// can (by obtaining the constructor argument
// for SpecialA in a different way)
Just realized how to solve the problem:
class SpecialA : public A {
public:
explicit SpecialA(Arg* arg) : SpecialA(arg, expensiveFunction(arg)) {}
private:
SpecialA(Arg* arg, T&& member) : A(member) , member(member) {};
T member;
}
Base class constructor must be called first.You cannot go any other way around but you can device a way to not make class A base class and call first whatever you want.
The base class is always fully constructed first. There is no way round this.
One alternative would be to break the inheritance and move the the base class to a member variable of the child class.
The order of member initialisation is then the order they appear in the class declaration.
But relying on this can make your code brittle, so do bear that in mind. Putting a suitable comment in the class declaration might not sufficiently discourage an enthusiastic refactorer.
The order of member initializers in the list is irrelevant: the actual
order of initialization is as follows:
1) If the constructor is for
the most-derived class, virtual base classes are initialized in the
order in which they appear in depth-first left-to-right traversal of
the base class declarations (left-to-right refers to the appearance in
base-specifier lists)
2) Then, direct base classes are initialized in
left-to-right order as they appear in this class's base-specifier list
3) Then, non-static data members are initialized in order of
declaration in the class definition.
4) Finally, the body of the
constructor is executed
Source: http://en.cppreference.com/w/cpp/language/initializer_list
in your case it looks like it would be more correct to invert the ownership of the item:
struct A
{
protected:
A(T expensive_object) : _expensive_object(std::move(expensive_object)) {}
protected:
T& access_expensive_object() {
return _expensive_object;
}
private:
T _expensive_object;
};
class SpecialA : public A {
public:
explicit SpecialA(Arg* arg)
: A(expensiveFunction(arg))
{}
void use_object() {
auto& o = expensive_object();
do_something_with(o);
}
};
Also you can use a reserved optional parameter as a placeholder:
class SpecialA : public A {
public:
SpecialA(Arg* arg, std::optional<T> reserved = {}) :
A(reserved = expensiveFunction(arg)),
member(reserved)
{}
private:
T member;
}
It can be better than delegating constructors because it bloats code less when there is a lot of parameters. Also there may be more overhead with delegating constructors (please, correct me if I'm wrong).

Does the order of base-class initializers and member variable initializers matter?

Is the order of the initializers for a class' constructor significant?
So say I have:
class MyClass : BaseClass
{
int a, b, c;
public:
MyClass(int);
}
e.g. 1:
MyClass::MyClass(int forBase) :
a(7),
b(14),
c(28),
BaseClass(forBase) { }
e.g. 2:
MyClass::MyClass(int forBase) :
BaseClass(forBase),
a(7),
b(14),
c(28) { }
Would example 1 do something different to example 2?
Would example 1 do something different to example 2?
No. Initialisation order is dictated by the standard, not by the order in which you write the initialisers:
[C++11: 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.
In fact, if you write them in any other order and one depends on the other, you may well be warned about it:
struct T {
std::vector<int> v;
int w;
T(int w) : w(w), v(0, w) {}
};
int main() {
T t(3);
}
// g++ 4.1.2:
// t.cpp: In constructor 'T::T(int)':
// Line 3: warning: 'T::w' will be initialized after
// Line 2: warning: '__gnu_debug_def::vector<int, std::allocator<int> > T::v'
// Line 5: warning: when initialized here
The order does not matter for the compiler (the initialization order is always base classes first, and always base classes in the order of derivation, and members in the order of declaration), but it does matter for the reader: It is very confusing if the order in which you give the initializers does not match the order in which they are executed. While in most cases it doesn't matter, in some cases you can create subtle bugs, e.g.
struct Derived: Base
{
int member;
Derived();
}
Derived::Derived():
member(3),
Base(member) // This is executed *before* member is initialized!
{
}
This bug would stand out more clearly if the initializers were given in the correct order:
Derived::Derived():
Base(member), // Now we see immediately that member is uninitialized
member(3),
{
}
It doesn't matter in which order you list the initializers in the constructor initialization list. Members are initialized in the order they are declared and base(s) are initialized before members.
However, listing initializers in a different order that that can bite you if a subobject's initial value depends on the values of other subobjects.
class A
{
int y, x;
A(int x_value): x(x_value), y(x) {}
};
Since y is initialized before x, it gets a garbage value, and the order of the initializer list just hides the bug. That's why this deserves a compiler warning.

Order of execution in constructor initialization list

Is order of execution in constructor initialization list determinable? I know that members order in a class is the order in which those members will be initialized but if I have scenario like this:
class X()
{
X_Implementation* impl_;
};
and then providing that allocator is available:
X::X():impl_(Allocate(sizeof(X_Implementation)))//HERE I'M ALLOCATING <--1
,impl_(Construct<X_Implementation>(impl_))//AND HERE I'M CONSTRUCTING <--2
{
}
but in order for this to be dependable this order MUST be from left to right. Is it guarantied by GREAT BOOK OF std:: or not? If not I can always move the second line into the body.
According to ISO/IEC 14882:2003(E) section 12.6.2:
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.
So, follow that order, and you'll have your order. Also according to the standard, the order is prescribed as such so that objects can be uninitialized in the precisely reverse order.
The C++ standard does guarantee an order for initialization lists (ISO C++ Standard 12.6.2/5):
...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).
(See Wyatt Anderson's answer for more information.)
Example:
class Foo
{
public:
Foo();
private:
A a;
B b;
C c;
};
Foo::Foo() : b(), a(), c() {
// a is initialized first, then b, then c - NOT b, a, then c!
}
However, you can't initialize a variable twice - what you have won't compile.
class X //() what's with the pair of parentheses you have in your code snippet?
{
public:
X();
private:
X_Implementation* impl_;
};
X::X():
impl_(Allocate(sizeof(X_Implementation))),
// It is not allowed to initialize a data member twice!
impl_(Construct<X_Implementation>(impl_)) {
}
Instead, just put the extra work into the constructor:
X::X() : impl_(Allocate(sizeof(X_Implementation))) {
impl_ = Construct<X_Implementation>(impl_);
}
There may be exception safety issues with the above code, but without knowing what Allocate() or Construct() actually does I'm not able to tell. I can tell you that it's best to separate allocation and construction into their own classes if you do that, using the Resource Acquisition Is Initialization (RAII) idiom:
class XBase
{
protected:
XBase() : impl_(Allocate(sizeof(X_Implementation))) { }
~XBase() {
if( !impl_) { Deallocate(impl_); } // Or something like this
}
X_Implementation* impl_;
};
class X : private XBase // XBase is an implementation detail
{
public:
X() {
impl_ = Construct<X_Implementation>(impl_);
}
~X() {
Destruct<X_Implementation>(impl_); // Or something like this
}
};
This way, if Construct() throws an exception, you won't leak memory since the base class destructor will be called which will deallocate the memory pointed by impl_. This is important because if the exception is not caught and leaves the constructor, its matching destructor will not be called. See Bjarne Stroustrup's paper on exception safety.
Your specific scenario is based on the idea of initializing the same member more than once. This is plain illegal in C++. Your code will not compile. So, the question you are asking doesn't really exist.
The order of member initialization is the order of their declaration in class definition. In no-inheritance contexts that covers everything related to the order of initialization in the constructions initializer list.