C++ 基类的构造函数和析构函数是否被派生类调用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1640414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:42:26  来源:igfitidea点击:

Does a base class's constructor and destructor get called with the derived ones?

c++

提问by josef.van.niekerk

I have a class called MyBase which has a constructor and destructor:

我有一个名为 MyBase 的类,它有一个构造函数和析构函数:

class MyBase
{
public:
    MyBase(void);
    ~MyBase(void);
};

and I have a class called Banana, that extends MyBase like so:

我有一个名为 Banana 的类,它像这样扩展了 MyBase:

class Banana:public MyBase
{
public:
    Banana(void);
    ~Banana(void);
};

Does the implementation of the new constructor and destructor in Banana override the MyBase ones, or do they still exist, and get called say before or after the Banana constructor / destructor executes?

Banana 中新的构造函数和析构函数的实现是否覆盖了 MyBase 的构造函数和析构函数,还是它们仍然存在,并且在 Banana 构造函数/析构函数执行之前或之后被调用?

Thanks, and my apologies if my question seems silly.

谢谢,如果我的问题看起来很愚蠢,我深表歉意。

采纳答案by Gy?rgy Andrasek

It should say

应该说

class Banana : public MyBase
{
public:
    Banana(void);
    ~Banana(void);
};

The constructor of the derived class gets called after the constructor of the base class. The destructors get called in reversed order.

派生类的构造函数在基类的构造函数之后被调用。析构函数以相反的顺序调用。

回答by Arkaitz Jimenez

A Base constructor will always be called before the derived constructor. The Base destructor will be called after Dervided destructor.

Base 构造函数将始终在派生构造函数之前被调用。Base 析构函数将在 Dervided 析构函数之后调用。

You can specify on derived constructor which Base constructor you want, if not the default one will be executed.

您可以在派生构造函数上指定所需的 Base 构造函数,否则将执行默认构造函数。

If you define other constructors but not default and don't specify on Derived constructor which one to execute it'll try default which doesn't exist and will crash compilation.

如果您定义了其他构造函数而不是默认构造函数,并且没有在派生构造函数上指定要执行的构造函数,它将尝试不存在的默认构造函数,并且会导致编译崩溃。

The above happens because once you declare one constructor no default constructors are generated.

发生上述情况是因为一旦您声明了一个构造函数,就不会生成默认构造函数。

回答by Mehrdad Afshari

Constructors cannot be overriden. You can't declare a base class constructor in a derived class. A class constructor has to calla constructor in base class (if one is not explicitly stated, the default constructor is called) prior to anything else.

构造函数不能被覆盖。您不能在派生类中声明基类构造函数。类构造函数必须在其他任何事情之前调用基类中的构造函数(如果没有明确说明,则调用默认构造函数)。

To be able to clean up the derived class correctly, you should declare the base class destructor as virtual:

为了能够正确清理派生类,您应该将基类析构函数声明为virtual

virtual ~MyBase() { ... }

回答by Mark Ransom

The constructors are called top down in the inheritance tree. This is so that the derived constructor can count on the base object being fully initialized before it tries to use any properties of the base.

构造函数在继承树中自上而下地调用。这样,派生构造函数就可以在尝试使用基对象的任何属性之前,依赖基对象已完全初始化。

Destructors are called in reverse order of the constructors, for the same reason - the derived classes depend on the base, but the base doesn't depend on the derived.

析构函数以与构造函数相反的顺序调用,原因相同——派生类依赖于基类,但基类不依赖于派生类。

If there is anypossibility of destroying the object through a pointer to a base class, you must declare all of the destructors virtual.

如果有任何通过一个指向基类的销毁对象的可能性,你必须申报所有的析构函数virtual

回答by David Rodríguez - dribeas

Constructors and destructors are special member functions. In general you will read everywhere that construction starts from the least derived type all the way in the hierarchy down to the most derived type. This is actually the order in which constructor execution completes, but not how construction is started.

构造函数和析构函数是特殊的成员函数。一般来说,你会在任何地方看到构造从层次结构中派生最少的类型一直到派生最多的类型。这实际上是构造函数执行完成的顺序,而不是构造开始的顺序。

Constructors initialization list execution order guarantees that while the most derived object's constructor will be the first constructor to start executing it will be the last constructor to complete

构造函数初始化列表的执行顺序保证,虽然最派生对象的构造函数将是第一个开始执行的构造函数,但它将是最后一个完成的构造函数

When you instantiate an object the most derived constructor that matches the construction call gets called first. The initialization list of the matched most derived constructor starts, and initialization lists have a fixed order: first the constructors of the base classes in order or appearance within the inheritance list get called. Then the member attribute constructors are called in the order in which they appear in the class declaration (not the order in which they appear in the initialization list). After the whole initialization list (at each level) completes, the constructor body block is executed, after which the constructor call completes.

当您实例化一个对象时,最先调用与构造调用相匹配的派生最多的构造函数。最匹配的派生构造函数的初始化列表开始,并且初始化列表具有固定的顺序:首先在继承列表中按顺序或出现的基类的构造函数被调用。然后按照它们在类声明中出现的顺序(而不是它们在初始化列表中出现的顺序)调用成员属性构造函数。在整个初始化列表(在每一级)完成后,构造函数体块被执行,之后构造函数调用完成。

All base destructors will be called in reverse order of construction after the most derived destructor has completed execution. Destruction happens in exact reverse order of construction.

在最派生的析构函数完成执行后,所有基础析构函数将以与构造相反的顺序调用。破坏的发生顺序与构造完全相反。

Destructors are special in a different way: they cannot be overriden. When you call the most derived destructor of a class, it will complete the execution of the destructor body, after which all member attribute destructors will be called in reverse order of creation. After the most derived destructor has completed and so have done the member destructors of the most derived object, the destructor of its most direct bases start in reverse order of construction, the destructor bodies will execute, then the member attributes destructors and so on... At the end all constructed elements will be destroyed.

析构函数的特殊之处在于:它们不能被覆盖。当你调用一个类最派生的析构函数时,它会完成析构函数体的执行,之后所有成员属性的析构函数将按照创建的逆序调用。在最派生的析构函数完成并完成最派生对象的成员析构函数后,其最直接基类的析构函数以与构造相反的顺序开始,析构函数体将执行,然后是成员属性析构函数,依此类推。 . 最后所有构造的元素都将被销毁。

Destructors for polymorphic classes should be virtual

多态类的析构函数应该是虚拟的

The destruction description above starts with the call to the most derived destructor. This can be achieved by calling deleteon a pointer to the most derived type, when an auto object goes out of scope or when the object is deleted through a base class whose destructor is virtual.

上面的析构描述从调用最派生的析构函数开始。这可以通过调用delete指向最派生类型的指针来实现,当自动对象超出范围或对象delete通过其析构函数为虚拟的基类时。

If you forget to add the destructor keyword in the base class and you try to delete a derived object through a pointer to the base you will call the base destructor directly, and that implies that all sub objects below the pointer type in the hierarchy will not be properly destroyed. All inheritance hierarchies in which you will delete objects through pointers to a base type musthave virtual destructors. As a general rule of thumb, if you already have any virtual method, the cost of making the destructor virtual is negligible and is a safe net. Many coding guides enforce that destructors in inheritance hierarchies must be virtual. Some go as far as requesting all destructors to be virtual, This has the intention of avoiding possible resource leaks at the cost of adding a vtable for all types and an vtable pointer for all objects.

如果您忘记在基类中添加析构函数关键字并尝试通过指向基类的指针删除派生对象,您将直接调用基类析构函数,这意味着层次结构中指针类型以下的所有子对象都不会妥善销毁。通过指向基类型的指针删除对象的所有继承层次结构都必须有虚拟析构函数。作为一般的经验法则,如果您已经拥有任何虚拟方法,那么将析构函数设为虚拟的成本可以忽略不计,并且是一个安全的网络。许多编码指南强制继承层次结构中的析构函数必须是虚拟的。有些甚至要求所有的析构函数都是虚拟的,这是为了避免可能的资源泄漏,代价是为所有类型添加一个 vtable,并为所有对象添加一个 vtable 指针。

回答by LiraNuna

You are missing the type of inheritance:

您缺少继承的类型:

Change

改变

class Banana:MyBase

To:

到:

class Banana: public MyBase

As for

至于

does the implementation of the new constructor and destructor in Banana override the MyBase ones, or do they still exist, and get called say before or after the Banana constructor / destructor executes?

Banana 中的新构造函数和析构函数的实现是否覆盖了 MyBase 的构造函数和析构函数,或者它们是否仍然存在,并且在 Banana 构造函数/析构函数执行之前或之后被调用?

The order of inherited executes from bottom to top, that means that MyBase will be called first, then Banana. If you had another subclass, it would be called last.

继承的顺序是从下往上执行,即先调用MyBase,再调用Banana。如果你有另一个子类,它会被最后调用。

Take this example:

拿这个例子:

class RottenBanana : public Banana

The inheritance chain is now RottenBanana -> Banana -> MyBase

继承链现在是 RottenBanana -> Banana -> MyBase

The constructors of this class will be called starting at MyBase, then Banana and then calling RottenBanana.

此类的构造函数将从 MyBase 开始调用,然后是 Banana,然后是 RottenBanana。

回答by Kurt Olsen

If you instantiate an EEGModeRGB object (which has tri-color led's attached) - then immediately delete it you'd see the colors Blue, Green, Yellow, and Red, for one second each - in that order.

如果您实例化一个 EEGModeRGB 对象(附有三色 LED) - 然后立即删除它,您将看到蓝色、绿色、黄色和红色,每个颜色一秒钟 - 以该顺序。

class EEGMode {
public:

   EEGMode()  { setAllPixelsToColor(BLUE); delay(1000); }
   virtual ~EEGMode()  { setAllPixelsToColor(RED); delay(1000); }

};


class EEGModeRGB : public EEGMode {
public:

    EEGModeRGB()  { setAllPixelsToColor(GREEN);  delay(1000); }
    virtual ~EEGModeRGB()  { setAllPixelsToColor(YELLOW); delay(1000); }

};