从具有非虚拟父级的虚拟类继承的正确方法继续



我的问题是基于这个问题:从具有非虚拟父级的虚拟类继承的正确方法。

我的理解正确吗?在问题中描述的情况下,新分配对象的"三"one_answers"二"部分正在泄漏,因为它们没有被破坏?

来源:

#include <iostream>
struct One
{
    ~One() {
        std::cout << "~One()n";
    }
};
struct Two : One
{
    virtual ~Two() {
        std::cout << "~Two()n";
    }
    virtual void test() = 0;
};
struct Three : Two
{
    virtual ~Three() {
        std::cout << "~Three()n";
    }
    virtual void test() {
        std::cout << "Three::test()n";
    }
};
int main()
{
    Two* two = new Three;
    two->test();
    One* one = two;
    delete one;
}

是的,没错。内存泄漏的定义是,您无法删除您创建的东西(因此您负责管理其生命周期)。

正如该问题的答案所示,delete one调用未定义的行为(在大多数情况下,这可能会转化为常规的旧内存泄漏,但情况可能会像鼻恶魔一样糟糕),因为指定对象的运行时类型与其静态(声明的)类型不匹配,并且静态类型没有虚拟析构函数。

C++标准的适用部分如下:

§5.3.5/3:在第一种备选方案(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数动态类型的基类,静态类型应具有虚拟析构函数或行为未定义。

解决方案是要么声明所有析构函数virtual,要么不通过指向One的指针删除对象。

最新更新