C++ 虚拟继承中的析构函数

C++ 虚拟继承中的析构函数,c++,destructor,delete-operator,virtual-inheritance,virtual-destructor,C++,Destructor,Delete Operator,Virtual Inheritance,Virtual Destructor,这导致崩溃,但我修改如下: class Base{}; class D1:virtual public Base{}; class D2:virtual public Base{}; class DD:public D1,public D2{}; int main(){ Base *pBase=new DD; delete pBase; } 然后,它通过了,但是默认的析构函数应该是虚拟伪函数,不是吗?这与虚拟继承无关 除非类型T是D的基类并且具有虚拟析构函数,否则通过指向类型

这导致崩溃,但我修改如下:

class Base{};
class D1:virtual public Base{};
class D2:virtual public Base{};
class DD:public D1,public D2{};

int main(){
    Base *pBase=new DD;
    delete pBase;
}

然后,它通过了,但是默认的析构函数应该是虚拟伪函数,不是吗?

这与虚拟继承无关

除非类型T是D的基类并且具有虚拟析构函数,否则通过指向类型T而不是原始分配的类型D的指针进行删除是未定义的行为

C++14(如N3936草案)§5.3.5/3 …如果要删除的对象的静态类型不同于其 动态类型,静态类型应是要删除的对象的动态类型的基类,并且 静态类型应具有虚拟析构函数或行为未定义

虚拟析构函数用于标识类型D,特别是它的大小和析构函数,可能还有它的自定义释放函数(您的代码中没有)


默认析构函数应该是虚拟伪函数,不是吗

不,不是

因为C++设计的一个指导原则是,你不为你不使用的东西付费,另外一个指导原则是让程序员控制,用表达任何需要的能力(例如,为了二进制的布局在内存中的目的)。


只有当基类具有虚拟析构函数时,才能获得默认的虚拟析构函数。

来自C++11规范(ISO/IEC 14882:2011(E)),第12.4节析构函数[class.dtor]:

第4分节:

如果类没有用户声明的析构函数,则析构函数将隐式声明为默认(8.4)。隐式声明的析构函数是其类的内联公共成员

第6分节:

当odr使用(3.2)销毁其类类型(3.7)的对象时,或者在第一次声明后显式默认时,默认且未定义为已删除的析构函数将隐式定义

最后,第9分节:

析构函数可以声明为虚拟(10.3)或纯虚拟(10.4);如果在程序中创建了该类或任何派生类的任何对象,则应定义析构函数。如果一个类有一个带有虚拟析构函数的基类,那么它的析构函数(无论是用户声明的还是隐式声明的)都是虚拟的

在最后一句话中强调我的观点


仅当基类具有虚拟析构函数时,编译器才会生成虚拟析构函数。如果基类没有虚拟析构函数,如第一个示例中的
base
,则子类将没有虚拟析构函数。如果一个类没有基类,编译器生成的析构函数将不是虚拟的。请不要用C++的代码> > TMGE</代码>来发布代码,除非它是VisualC++特定代码。它让其他人更难尝试你的代码,并教会新手养成良好的习惯。帮你修好了。只需使用一个标准的
int main()
virtual
在语句中做什么:
classd:virtualpublic Base
?我从未见过这种构造(这可能是我的无知…。@Chiel,当您继承共享同一个基的多个类时使用它。隐式声明的析构函数不是虚拟的。尽管如此,您的代码在
clangg
g++
中都可以编译,并且在这里也不会崩溃。
class Base{
public:
    virtual ~Base(){};
};

class D1:virtual public Base{
public:
    virtual ~D1(){}
};

class D2:virtual public Base{
public:
    virtual ~D2(){}
};

class DD:public D1,public D2{
};