Does an inheritance chain create a chain of constructor calls? - c++

I've been struggling with the concept of constructors in the context of inheritance. This confusion has been compounded by the fact that big changes were introduced to this topic with C+11 (i.e. base constructors can be inherited?).
So my question:
Assuming I don't use constructor inheritance, but just define a new constructor in my derived class, does the base constructor still get called? It seems like it shouldn't, but I've come across some documents stating that this does occur. Furthermore, does that mean when you have an inheritance chain, there will be a series of constructors called? If so, in what order? Base before derived, or derived before base?
Thank you!

Here is the order:
Here’s what actually happens when derived is instantiated:
Memory for derived is set aside (enough for both the Base and
Derived portions)
The appropriate Derived constructor is called
The Base object is constructed first using the appropriate Base constructor. If no base constructor is specified, the default
constructor will be used.
The initialization list initializes variables
The body of the constructor executes
Control is returned to the caller
Hope it helps.

Related

C++ child constructor and VPTR

In many sources, books etc. are written "don't call this->virtualFunction in child class constructor" and in some sources explain why you mustn't do it. Because at the moment of construction class isn't created at all. So virtual function that will be called from child constructor will be function of base class. It means that in child constructor body VPTR of that class pointed to base VTABLE.
So my question is,
what is the moment in object construction when VPTR of child class will be overriden to address on it's virtual table? I guess that some automatically generated code do it at end of constructor body or after constructor body will be executed.
And second question is,
why is VPTR overriden at the end of construction? Maybe for it have some important reasons?
Why can't override VPTR at beginning constructor body or after base class constructed?
Child::Child() :
Base()
//<----- Why not here?
//members initialization
{
//<----- Why not here?
//code
}
In many sources, books etc. are written "don't call this->virtualFunction in child class constructor"
I doubt that. It's often advised not to call virtual functions from the base class constructor, to avoid confusion if you expect them to call the final overrides, not the base-class versions. And you must certainly not call them from the base class if they are pure virtual there - that gives undefined behaviour.
Within the derived class constructor, they are well-defined and do what you would expect.
So virtual function that will be called from child constructor will be function of base class.
No, during the child's constructor body, the dynamic type is Child, and virtual functions calls will use the Child overrides.
what is the moment in object construction when VPTR of child class will be overriden to address on it's virtual table?
After all base class constructors have completed, and before child class members are initialised. Child member functions, including virtual functions, can be called from member initialisers (but not base class initialisers) or the constructor body.
You need to be careful calling them from member initialisers, since they might access uninitialised members. But within the constructor body, all base objects and members are initialised, so they are quite safe.
why is VPTR overriden at the end of construction?
It isn't. It happens at the first point you indicate with <----- Why not here?.
I disagree with your overly simplified reason to why you shouldn't call a virtual function. First of all, a VTABLE is not actually defined by the C++ standard, and is, in fact, implementation specific:
When is VTable in C++ created?
Calling a virtual function from a constructor is allowed by the standard, and should actually should call correctly within the hirearchy at that level (with some limitations)
C++ constructors: why is this virtual function call not safe?
http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctors.html
However, there are many, many reasons not to do this.
The constructor for the derived class has not been called yet. Any access of any members of the derived class will yield undefined behavior.
There is a rule of thumb that you should keep constructors as simple and dumb as possible. This is due to the fact that error handling in constructors can be a giant pain due to destructor not being called and the only way to return a sensical error state is to throw an exception.
This will often break the dependency inversion principal, and may cross the line of demeter, and will usually introduce high coupling to the code.

Virtual Constructor Idiom - Virtuous Or Complete Utter Fallacy

One of the golden rules in C++ is that the life-time of an instance begins when its constructor completes successfully and ends when its destructor begins.
From this rule we conclude that it is NOT a good idea to call virtual methods in a constructor as the possible derived instance is not valid which would lead to undefined behavior.
The Virtual Constructor Idiom as mentioned in C++ FAQ 20.8 seems to indicate the contrary.
My question is:
What is the exact definition in the standard for defining the life time of objects relative to calls from their constructors and destructors?
and furthermore is the So called "Virtual Constructor Idom" valid?
I think you're confusing two separate (if vaguely related) things.
It is well-known that one shouldn't call virtual functions from constructors (directly or indirectly), for reasons discussed here.
What the FAQ is talking about is calling a constructor from a virtual function. In some sense it is the opposite of #1. The idea is to choose the constructor (i.e. the class) based on the dynamic type of some existing object.
An object exists as the type of the class the constructor belongs to when the constructor starts, the object just may be in an inconsistent state (which is fine, as execution is currently inside one of the object's methods). That is, an object that is actually of type Derived that inherits from Base is treated as a Base in Base constructors; this in any Base::Base() is treated as a Base *, no matter the actual type of the object that this points to. Calling virtual methods is fine. In a constructor, the virtual methods for the constructor's class will be called, rather than for the actual type of the object.
Your first question is covered in "Base class on the initialisation list of a derived class' copy constructor". The short answer is it's covered by § 12.7 2-3 of C++03.
The virtual constructor idiom is completely valid.

What happens if you don't call the base constructor from the derived constructor?

Is it always necessary to call base class constructor from derived class constructor? What happens when you don't call it?
Assuming you're talking about C++ (anyway, this should be similar in most other languages), if you don't call a constructor of the base class explicitly, its default constructor will be called automatically (if one exists; if not, the compiler would fire an error).
Nothing at all, since it's absolutely impossible not to do so.

Constructors cannot be virtual, why? Not a dupe [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why do we not have a virtual constructor?
I know this has been asked before but I didn't understand the complex technical words used in the other answers.
I read on a community the reason that constructors cannot be virtual is
The ‘virtual’ mechanism works on a logically complete (completely constructed) object. We know that we use constructors to logically initialize our objects. In other words, the object is not completely constructed until the constructor has finished executing. Thus, we can’t have virtual constructors.
There is a misconception that by then virtual table is incomplete so we can’t have virtual constructors. Just before the constructor starts executing the virtual table is properly constructed and the ‘this’ pointer passed to the constructors. Moreover, virtual table mechanism is implementation depended, and finds no place in the C++ standard. And hence, to argue over this issue using the virtual table concept is illogical.
Now, as the constructor finishes executing any other function can be virtual. Destructor is no exception to this rule as it is a function. Virtual destructors are required in case we use a base class pointer to refer to a derived class object, use it, and then delete it. If we have virtual destructor, using ‘delete’, a chain of destructors is called starting from the derived to the base. But, had there been no ‘virtual’ in destructor only the base class destructor is called (and not the derived). This (may) generate inconsistencies in the program.
Is the above reason correct? The answer doesn't talk about the static and dynamic types of objects.
Virtual constructors don't make sense and aren't necessary. The only time you call a constructor is when creating an object. You need to know the type of an object in order to create it, so the static and dynamic types are the same, and the correct constructor to call is the one for that type.
That's why they aren't necessary. Why they don't make sense, is that when creating an object, base class constructors are called as well as derived class constructors. If the base class constructor was overridden in the derived class, is that supposed to mean that the base class constructor isn't called after all?
Other languages have virtual constructors, perhaps because constructors in those languages are methods, and they only have virtual invocation for non-static methods. But those other languages (Java and Python spring to mind) have to introduce special rules that constructors must/should construct their base class explicitly as a call from the constructor. C++ just does it (perhaps in an initializer list, if the base class constructor requires parameters), using non-virtual constructors, and there is no option to enter the body of the constructor with uninitialized base class sub objects.
To quote from The C++ Programming Language:
To construct an object, a constructor
needs the exact type of the object it
is to create. Consequently, a
constructor cannot be virtual.
Furthermore, a constructor is not
quite an ordinary function. In
particular, it interacts with memory
management routines in ways ordinary
member functions don’t. Consequently,
you cannot have a pointer to a
constructor.
It must be interesting to note that C++ do have an idiom called virtual constructor. You can read more about that here.
Yes, the reason is you need to have a pointer/reference to a complete object already before you can call a virtual function. When the constructor is being invoked there's no complete object yet. Even more, when you do new SomeClass() you don't even have a pointer yet - the pointer is returned upon the new statement is completed successfully.
The virtual keyword cannot be applied to a constructor since a constructor turns raw bits into a living object, and until there is a living object against which to invoke a member function, the member function cannot possibly work correctly. Instead of thinking of constructors as normal member functions on the object, imagine that they are static member functions that create objects. - C++ FAQs

How are constructors and destructors implemented in C++?

I have 2 classes Base and Derived (derived publically from Base).
When I write -
Derived * d1 = new Derived;
delete d1;
Compiler sees that d1 is a Derived type object. So it calls the derived class constructor (which calls the base class constructor). I have 2 questions here -
1) Why do we follow this order?
2) How do these constructors work together to allocate memory? I need some implementation details
Now the next statement is delete d1. So compiler sees that d1 is a derived type object and so calls the destuctor of derived class (which calls the destructor of base class after deleting the derived class members). I have one question here -
1) How do these destructors work together? Lets say the derived class destructor is passed the address of d1 in memory. How do these destructors free up the space now?
That code will not compile. You cannot deletean automatic instance, you must use new to allocate the instance in order to use delete on it.
When it comes to constructor order, I guess it just makes sense to run them so that more specialized classes can depend on the more general parts having already been done.
The memory layout of each class is known by the compiler, from inspecting the complete class declaration and recursing up through any and all superclasses.
1) By default, the base class constructor is called automatically. However, the derived constructor is allowed to call the base class constructor explicitly in its initializer list. This would not be possible if the constructors were not executed derived-class-first.
Derived::Derived() : foo( 42 ), bar( 7 ), Base( 1, 2 ) { }
2) The compiler knows the memory footprint of the derived class (as all member variables are known at compile time), and allocates enough memory to hold both the base class and the derived class members. Details on the memory layout are specified by the ABI used by your system.
3) Destructors do more than just freeing up the memory. Actually, the destructors do not free up memory required to hold any member variables - only, where necessary, memory that member pointers point to.
(1) The base class does not depend on the derived class, but the other way around is possible. I.e. a Base class cannot know which fields any Derived class has, so Base::Base won't and can't touch them. The other way around is possible, Derived::Derived can access Base::member. Therefore, Base::member is initialized by Base::Base before Derived::Derived gets the chance to useBase::member`.
(2) constructors don't allocate memory. That's new's task. Or if the object is a global, the compilers'. The constructor is called with this already pointing to the allocated memory; it need just fill in the members at that location.
In the case of a base and derived constructor, one common implementation inserts the call to the Base constructor in the generated code for the Derived constructor. With single inheritance, the Base and Derived class usually share the same this pointer, so the Derived constrcutor can then pass the same pointer that it got.
(1) [sic] Just like constructors don't allocate memory, destructors don't free it. That's the task of delete - and again, for globals the compiler would do it.
The code example you give wouldn't compile. delete works on pointers, not objects.
I don't think C++ itself (the language standard) says anything about how memory is used to represent instances of types that use inheritance. However, in most implementations a single chunk of memory is allocated from the free store that is large enough to hold all the data of Base and Derived. When an instance of Derived is deleted, both constructors run and then the single memory block is freed.
Similarly, if an instance of Derived is an embedded data member of some class Container, then the memory block that holds an instance of Container will be made large enough to hold Derived (and hence Base) and all the other data of Container.
When constructing, constructors are called from the highest base class until the oneof the most derived, which will be called the latest.
When destructors are called, it's the reverse order. First is called the destuctor of the most derived, until the one of the highest base class.
While in inheritance, the compiler should know what it is inheriting. It should know what the Base class consists of. It cannot inherit from a class, which it doesn't have any idea..
So, it does make sense that the Base class constructor is called first and then the Derived.
And in the case of Destruction, if the Base destructor is being called first and gets destructed, the Derived class may still be using the Base class members which becomes invalid.. Hence the Destruction is the exact inverse of the construction..