Constructor and destructor Calls

2019-07-24 23:18发布

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)

标签: c# c++ oop
3条回答
孤傲高冷的网名
2楼-- · 2019-07-24 23:55

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.

查看更多
Summer. ? 凉城
3楼-- · 2019-07-24 23:55

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.

class Base {
    int x;
public:
    Base() : x(42) {}
};

class Derived : public Base {
    int y;
public:
    Derived() : Base(), y(1337) {}
    // is the same as: Derived() {}
};

Here, Base() isn't possible (it doesn't provide a default constructor):

class Base {
    int x;
public:
    Base(int x) : x(x) {}
};

class Derived : public Base {
    int y;
public:
    Derived() : Base(),   y(1337) {}  // <-- error!
    Derived() : Base(42), y(1337) {}  // <-- ok!
};

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.

查看更多
看我几分像从前
4楼-- · 2019-07-25 00:01

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:

class BaseMember
{
public:
    bool Pred();
};

class DerivedMember
{
public:
    void DoFirst(bool);
    void DoLast(bool);
};

class Base
{
public:
    Base() {baseMember=new BaseMember;}
    ~Base(){delete baseMember;}
protected:
    BaseMember *baseMember;
};

class Derived: public Base
{
public:
    Derived()
    {
        derivedMember=new DerivedMember;
        derivedMember->DoFirst(baseMember->Pred());
    }
    ~Derived()
    {
        derivedMember->DoLast(baseMember->Pred());
        delete derivedMember;
    }
protected:
    DerivedMember *derivedMember;
};

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.

查看更多
登录 后发表回答