虚拟继承中的析构函数
Destructor in virtual inheritance
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;
}
这会导致崩溃,但我修改如下:
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{
};
然后,它通过了,但默认析构函数应该是虚拟虚拟函数,不是吗?
根据 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
(,则子类将没有虚拟析构函数。如果一个类没有基类,编译器生成的析构函数将不是虚拟的。
这与虚拟继承无关。
通过指针删除类型 T 而不是最初分配的类型 D 是未定义的行为,除非类型 T 是 D 的基类并且具有虚拟析构函数。
C++14(如N3936草案(§5.3.5/3">...如果要删除的对象的静态类型与其 动态类型,静态类型应是要删除的对象的动态类型的基类和 静态类型应具有虚拟析构函数或行为未定义。
虚拟析构函数用于标识类型 D,特别是其大小和析构函数,可能还有其自定义释放函数(您的代码没有该函数(。
再
"> 默认析构函数应该是虚拟虚拟函数,不是吗?
不,不是。
因为C++设计的一个指导原则是你不为不使用的东西付费,另一个指导原则是让程序员控制,能够表达任何需要的东西(例如,为了内存中的二进制布局(。
仅当基类具有虚拟析构函数时,才会获得默认虚拟析构函数。
- C++ std::vector 中的虚拟析构函数继承
- 继承的类析构函数
- 抽象类析构函数与继承"Shutdown"函数
- C++虚拟继承、虚拟析构函数和 dynamic_cast<void*>
- 如果不手动完成,子类是否继承父类的析构函数?
- 从 std::streambif 继承时不兼容析构函数编译器警告
- 多重继承析构函数调用他自己和父析构函数?c++
- 为什么我在使用组合而不是继承时得到 C4624(无法访问基类析构函数)
- 抽象基类中的析构函数保护不会在 C++ 中继承
- C++继承和构造函数、析构函数
- 从 STL 容器继承并删除"新"运算符以防止由于缺少虚拟析构函数而导致未定义的行为是否有意义?
- 虚拟继承中的析构函数
- 复制、移动、交换、赋值和析构函数的C++继承?我需要哪个
- 在不使用虚拟析构函数的情况下删除继承的对象时中止
- C++析构函数继承
- C++非抽象析构函数继承
- 构造函数和析构函数继承
- C++析构函数-继承上下文中的显式调用
- 非虚拟平凡析构函数 + 继承
- C++构造函数/析构函数继承