Lack of virtual destructor when doing “delete this”
C++FAQ Lite的第16.15节讨论EDCOX1×0,然后提到:
Naturally the usual caveats apply in cases where your this pointer is
a pointer to a base class when you don't have a virtual destructor.
为什么是这样?考虑此代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class ISuicidal { public: virtual void suicide() = 0; }; class MyKlass : public ISuicidal { public: MyKlass() { cerr <<"MyKlass constructor "; } ~MyKlass() { cerr <<"MyKlass destructor "; } void suicide() { delete this; } }; |
因此使用:
1 2 3 4 5 6 | int main() { ISuicidal* p = new MyKlass; p->suicide(); return 0; } |
在调用
对我来说这是有意义的,因为在
那么,常见问题条目是不准确,还是我误解了?
在你的功能中,
如果您已经在isoidicial中定义了函数,那么它不会调用myklass的析构函数,除非您在isoidical中声明了一个虚拟析构函数。
你是误会。在isoidicial中实现自杀函数(即delete this),您会发现当此指针是调用delete的基类时,它不会调用派生类的析构函数。
~Child () {}
};
如果在层次结构中引入从myClass派生的另一个实类(例如myClass2),则会出现问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | class ISuicidal { public: virtual void suicide() = 0; }; class MyKlass : public ISuicidal { public: MyKlass() { cerr <<"MyKlass constructor "; } ~MyKlass() { cerr <<"MyKlass destructor "; } void suicide() { delete this; } }; class MyKlass2 : public MyKlass { public: MyKlass2() { cerr <<"MyKlass2 ctr"<<std::endl; } ~MyKlass2() { cerr <<"MyKlass2 dtr"<<std::endl; } } int main() { MyKlass* p = new MyKlass2; delete p; //destructor of base class called, not the destructor of MyKlass2 because //the destructor is not virtual return 0; } |
我想你误解了。当您在基类中调用delete this时,即当此指针具有指向该基类的指针类型时,就会发生此问题。
Naturally the usual caveats apply in cases where your this pointer is
a pointer to a base class when you don't have a virtual destructor.
在您的示例中,这不是指向基类的指针,而是指向派生类的指针。
只要您调用实例的确切析构函数(例如,不要调用基的析构函数),它是安全的。
因此,您可以通过为每个子类正确地实现