对象的销毁是否正确发生?

Is the destruction of the objects properly happend?

我在这里阅读了这篇文章:When to use virtual destructors? 我的想法是,每当我们使用 new 或智能指针动态创建对象时,基础 class 应该有一个适当的 virtual 析构函数用于在删除时销毁对象。

然后我发现了一些类似下面的代码(简化形式),它错过了 Base 中的 virtual 析构函数:

class Base
{
public:
    // some static members
};

class Derived1 final : public Base
{
public:
    // other members
    // default constructor does not construct the `Base` in constructor member intilizer
    Derived1() {};
    virtual ~Derived1() = default;
};
class Derived2 final : public Base
{
public:
    // other members
    Derived2() {}; // default constructor does not construct the `Base`
    ~Derived2() = default;
};

int main()
{
    // creating Derived1 dynamically        // 1
    Derived1 *d1Object = new Derived1{};

    // creating Derived2 dynamically        // 2
    Derived2 *d2Object1 = new Derived2{};

    // creating Derived2 statically         // 3
    Derived2 d2Object2{};

    // clean up
    delete d1Object;
    delete d2Object1;
}

我的问题是:

我正在使用 C++11。

该代码中的 object 指针 实际上不是多态的*d1Object 的静态类型与其动态类型相同,即 Derived1&(其他object同理)。

因此,直接销毁它会调用正确的析构函数,~Derived1。因此一切都很好。以下代码出现问题:

Base* b = new Derived1();
delete b;

这隐式调用了 b->~Base();。由于 ~Base 不是虚拟的,因此 ~Derived1 不会 被调用,因此您会得到 UB。

std::unique_ptr<Base>也是如此。然而,对于 std::shared_ptr<Base> 来说 not 是真的,因为 shared_ptr<> 构造函数是模板化的,并且存储了构造它的实际 object 的析构函数。也就是说,以下内容很好并且为 objects:

调用了正确的析构函数
std::shared_ptr<Base> p1{new Derived1{});
std::shared_ptr<Base> p2 = std::make_shared<Derived1>();

至于你关于构造函数的问题,与数据成员的问题相同:即使它们不在初始化列表中,它们仍然按照声明的顺序进行默认初始化,并且在 base [= 的情况下40=]es,从最远到最近的顺序 parent。换句话说,你不能初始化一个parentclass,它总是会发生。

问题 1:在任何情况下(1、2、3)我是否有未定义的行为?为什么?

提供的代码示例中没有未定义的行为。 如果您尝试持有指向 Base 的指针并通过该指针进行删除,则会出现未定义的行为。在提供的示例中,您知道正在删除的具体 class

问题2:在两个派生的classes的构造函数的成员初始值设定项列表中,构造Base不是必需的(在上面的特定例)?

基础 class 构造函数总是被调用,无论您是否显式调用它。如果没有显式调用,将调用默认构造函数。如果没有默认的、无参数的构造函数并且您不调用特定的构造函数,代码将无法编译。