所以我一直试图通过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
现在有三个问题:
delete d
的情况下运行代码时,执行就停止了,而没有打印任何内容)。根据维基百科的文章virtual_table,对象c获得的地址比d和b获得+8字节,在e情况下会发生这种情况。
地址通常与编译器相关,因此非常容易。我不会依靠它们的任何特殊价值。
[当我调用delete b而不是delete d时,也会获得相同顺序的虚拟析构函数,因此为什么要调用派生类析构函数
指针的类型无关紧要。基础对象是使用new D()
创建的,因此这些是被调用的析构函数。这是因为否则可能很难正确删除对象-如果您有一个创建各种子类的工厂,您如何知道将其删除为哪种类型?
仅当我删除一个对象时才调用虚拟析构函数,然后在程序结束时如何删除vtable和vpointers(当我运行不带delete d的代码时,执行就停止了,而没有打印任何内容)。
如果您从不删除任何内容,则永远不会对其进行清理。程序结束时没有从堆中释放该内存。这是“内存泄漏”。程序结束后,操作系统将一次性清理整个程序堆(无需关心其中的内容)。