When we create an object of a derived class, why are the constructors called in a top-to-bottom fashion (first the base constructor, then derived constructor) and are destructors called bottom-to-top (first derived constructor, then base constructor)
相关问题
- how to define constructor for Python's new Nam
- Sorting 3 numbers without branching [closed]
- Sorting 3 numbers without branching [closed]
- Graphics.DrawImage() - Throws out of memory except
- Why am I getting UnauthorizedAccessException on th
To explain for newbies, consider you are constructing a new building.
You Construct basement, first floor, 2nd floor. While destroying , you destroy 2nd Floor, First Floor, and basement.
The same way, construction/destruction of a object happens in C++.
Hope this helps to understand.
Memory allocation is independent of calling constructors and destructors. When constructing a derived object, memory for the whole type will be allocated.
Then, its constructor is called (not the base constructor). However, this constructor first calls the base class constructor. Per default, the base's default constructor gets called, but you can specify how to call the base constructor within the derived constructor. If no such exists and you don't specify how to construct the base class, it's a compile error.
Here,
Base()
isn't possible (it doesn't provide a default constructor):So as you can see, technically the derived constructor is the first one being called. But since it calls the base constructor at the very beginning, it's effectively the other way around: The base is constructed, then the derived class "adds" its own stuff.
The destruction is simply the other way around: An instance of the derived class needs to clean up the stuff it adds to the base class before the base can be destructed.
Think of this simply as building a house: You have to build the base first, then add the stories, finally the roof. When destructing, first remove the roof, then the stories and finally get rid of the base.
It's the consequence of another rule: all the base constructors are called before entering the body of the derived constructor, and all the base destructors are called after leaving the body of the derived destructor.
Consider this (oversimplified) code:
We can write something like that because we rely on Base being fully constructed (all the Base's bases constructors are finished, all the Base member constructors are finished too, Base's constructor body is finished) before we enter the body of Derived constructor. This way, we can use all the bases' members knowing they are constructed. When we enter the body of Derived destructor, we have knowledge that nothing has been destructed yet, so we can use all the bases' members knowing they still exist and will be destructed later.
Constructor/Destructor call hierarchy is the consequence of this logic. If we call Base constructor before entering the body of the Derived(), and Base itself is derived from BaseOfBase, then the Base constructor will call BaseOfBase() constructor before entering the body of Base(). If we call the ~Base() destructor after leaving the ~Derived() destructor's body, then the ~BaseOfBase() destructor will be called after the ~Base() destructor has finished.
In C++, multiple inheritance (and virtual inheritance) will complicated call hierarchy further, but the same logic applies in such cases, too.