我试图通过以下示例来理解C ++中的破坏行为: https://github.com/peterdemin/virtual-destruction-5-cents
该列表是否满足所有可能的流量? 应该添加什么? 如何将给定的例子转换成短期条款?
https://stackoverflow.com/a/461224/135079提出“永远使基类”的析构函数在被多态操作时是虚拟的。“这不包括场景4。
Scott Meyers的有效C ++中的第7项规定:
很轻(应该且不应该)并且面对场景2。
我将6502提供的C ++标准重写为伪代码:
if static type of object is different from its dynamic type:
if the static type is a base class of the dynamic type:
if the static type has a virtual destructor:
We're fine - dynamic type's destructor will be called
else:
behavior is undefined [1]
else:
behavior is undefined [2]
[1]代码将在没有警告的情况下进行编译,并且可能正常工作,但不能保证并且可能在运行时导致纠缠错误。
[2]那很尴尬:
class A {};
class B {};
B *a = (B*)(new A());
delete a;
答案 0 :(得分:7)
使用基指针销毁派生对象并且析构函数不是虚拟的时,最终会出现“未定义的行为”情况。
在第一个替代(删除对象)中,如果是静态类型的 要删除的对象不同于其动态类型,静态 type应该是对象的动态类型的基类 删除和静态类型应具有虚拟析构函数或 行为未定义
解释说明github存储库是完全错误的(“派生的析构函数未被调用,但没有发生内存泄漏”)。你不能指望它。
我没有阅读其余部分,因为这会浪费时间。 UB是UB ...试图描述undefined是无意义的。
答案 1 :(得分:-1)
当您声明方法virtual时,这意味着您正在指示编译器在处理派生类对象时应始终搜索方法的派生版本。就这么简单。
在下面的示例中,如果在基类方法中不使用virtual关键字,则将调用方法的基类版本。
#include <iostream>
class A
{
public:
virtual const char* fetchClassName() { return "A"; }
// this is a virtual destructor:
virtual ~A(){ cout<<"Destroying Base";}
};
class B: public A
{
public:
virtual const char* fetchClassName() { return "B"; }
virtual ~B(){ cout<<"Destroying Derive";}
};
int main(void)
{
B obj_b;
A &obj_a = obj_b;
std::cout << obj_a.fetchClassName() << "\n";
}