C++ 执行“时缺少虚拟析构函数”;删去这句话;

C++ 执行“时缺少虚拟析构函数”;删去这句话;,c++,polymorphism,virtual-destructor,self-destruction,C++,Polymorphism,Virtual Destructor,Self Destruction,本节讨论了删除此,然后提到: 当然,通常的警告适用于您的this指针不可用的情况 没有虚拟析构函数时指向基类的指针 为什么这是真的?考虑这个代码: class ISuicidal { public: virtual void suicide() = 0; }; class MyKlass : public ISuicidal { public: MyKlass() { cerr << "MyKlass constructor\n"; }

本节讨论了删除此,然后提到:

当然,通常的警告适用于您的this指针不可用的情况 没有虚拟析构函数时指向基类的指针

为什么这是真的?考虑这个代码:

class ISuicidal {
public:
    virtual void suicide() = 0;
};

class MyKlass : public ISuicidal {
public:
    MyKlass() {
        cerr << "MyKlass constructor\n";
    }

    ~MyKlass() {
        cerr << "MyKlass destructor\n";
    }

    void suicide() {
        delete this;
    }
};
在调用
p->sequestion()
时,会按预期调用
MyKlass
的析构函数,即使
ISuicidal
没有虚拟析构函数

对我来说,这是有意义的,因为在
MyKlass::sequestion
中,
this
的静态类型是
MyKlass*
,因此调用了正确的析构函数。这很容易通过将
typeid
调用放在
sequestion
中进行验证


那么,FAQ条目是否不准确,或者我是否误解了它?

只要您调用实例的确切析构函数(例如,不要调用基的析构函数),它是安全的


因此,您可以通过正确地为每个子类实现
自杀()
,或者创建一个可供
this
访问的外部deleter函数(或者管理
this
生命周期的任何函数),安全地完成这一任务。

您误解了。在ISuicidal中实现自杀函数(即delete this),您会发现,当this指针是一个调用delete的基类时,它不会调用派生类的析构函数。

我认为您误解了它。当在基类中调用delete this时,即this指针具有指向基类的指针类型时,就会出现问题

当然,通常的警告适用于您的this指针不可用的情况 没有虚拟析构函数时指向基类的指针


在您的示例中,这不是一个指向基类的指针,而是一个指向派生类的指针。

在您的函数
sequestion(),
您正在使用
删除此项
这里,
this
指针对应于类MyKlass,因为函数在MyKlass中定义,而不是ISuicidal,因此调用MyKlass的析构函数


如果您在iUICIDAL中定义了该函数,那么它不会调用MyKlass的析构函数,除非您在iUICIDAL中声明了一个虚拟析构函数。

如果您在层次结构中引入从MyClass派生的另一个实类(例如MyClass2),则会出现问题

类是杀人犯{
公众:
虚空自杀()=0;
};
MyKlass类:公共杀虫药{
公众:
MyKlass(){

cerr
类子类:公共MyKlass{
~Child(){}
};

ISuicidal*p=新子女;


p->sequestion();//~Child()未调用!

现在只需:行为未定义。
int main()
{
    ISuicidal* p = new MyKlass;
    p->suicide();
    return 0;
}
class ISuicidal {
public:
    virtual void suicide() = 0;
};

class MyKlass : public ISuicidal {
public:
    MyKlass() {
       cerr << "MyKlass constructor\n";
    }

    ~MyKlass() {
        cerr << "MyKlass destructor\n";
    }

    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;
}