在C ++中调用虚拟析构函数的顺序

问题描述 投票:0回答:1

所以我一直试图通过C ++理解OOP概念,但是我无法获得虚拟析构函数的某些部分。

我写了一个小片段:

class A{
    int x;
public: 
    virtual void show(){
        cout << " In A\n"; 
    }
    virtual ~A(){
        cout << "~A\n";
    };
};

class B: public A{
    int y;
public: 
    virtual void show(){
        cout << " In B\n"; 
    }
    virtual ~B(){
        cout << "~B\n";
    };
};

class C: public A{
    int z;
public: 
    virtual void show(){
        cout << " In C\n"; 
    }
    virtual ~C(){
        cout << "~C\n";
    };
};
class E: public A{
    int z;
public: 
    virtual void show(){
        cout << " In E\n"; 
    }
    virtual ~E(){
        cout << "~E\n";
    };
};

class D: public B , public C , public E{
    int z1;
public: 
    virtual void show(){
        cout << " In D\n"; 
    }
    virtual ~D(){
        cout << "~D\n";
    };
};

signed main(){
    // A * a = new A();
    // B *b = new B();
    D *d = new D();
    B *b = d;
    C *c = d;
    E * e = d;
    A * a = new A();
    cout << d << "\n";
    cout << b  << "\n";
    cout  << c << "\n";
    cout << e << "\n";
    delete b;
    // a -> show();

}

在运行代码时,我得到的结果为:

0x7f8c5e500000
0x7f8c5e500000
0x7f8c5e500018
0x7f8c5e500030
~D
~E
~A
~C
~A
~B
~A

现在有三个问题:

  • 根据Wikipedia文章virtual_table,引用对象c获得的地址比d和b获得+8字节,在e情况下会发生这种情况。
  • [当我调用delete b而不是delete d时,也会得到相同顺序的虚拟析构函数,所以为什么派生类析构函数称为
  • [仅当我删除对象时才调用虚拟析构函数,然后在程序结束时如何删除vtable和vpointers(当我在没有delete d的情况下运行代码时,执行就停止了,而没有打印任何内容)。
c++ oop destructor virtual-inheritance virtual-destructor
1个回答
0
投票

根据维基百科的文章virtual_table,对象c获得的地址比d和b获得+8字节,在e情况下会发生这种情况。

地址通常与编译器相关,因此非常容易。我不会依靠它们的任何特殊价值。

[当我调用delete b而不是delete d时,也会获得相同顺序的虚拟析构函数,因此为什么要调用派生类析构函数

指针的类型无关紧要。基础对象是使用new D()创建的,因此这些是被调用的析构函数。这是因为否则可能很难正确删除对象-如果您有一个创建各种子类的工厂,您如何知道将其删除为哪种类型?

仅当我删除一个对象时才调用虚拟析构函数,然后在程序结束时如何删除vtable和vpointers(当我运行不带delete d的代码时,执行就停止了,而没有打印任何内容)。

如果您从不删除任何内容,则永远不会对其进行清理。程序结束时没有从堆中释放该内存。这是“内存泄漏”。程序结束后,操作系统将一次性清理整个程序堆(无需关心其中的内容)。

© www.soinside.com 2019 - 2024. All rights reserved.