c++11 - 隐式声明的析构函数
问题描述
如果我是正确的,默认的析构函数总是隐式声明的,除非用户声明它。根据cppreference:
通过指向基类的指针删除对象会调用未定义的行为,除非基类中的析构函数是虚拟的
现在,考虑这个例子:
struct B {};
struct D : B {};
隐式声明的析构函数是B::~B()
虚拟的吗?如果不是,我应该在使用继承时总是声明一个虚拟析构函数吗?
解决方案
隐式声明的析构函数 B::~B() 是虚拟的吗?
不,根据class.dtor/3:
类 X 的隐式声明的预期析构函数将具有以下形式
~X()
当然,根据class.dtor/12:
如果一个类有一个带有虚拟析构函数的基类,那么它的析构函数(无论是用户声明的还是隐式声明的)都是虚拟的
如果不是,我应该在使用继承时总是声明一个虚拟析构函数吗?
C++ 核心指南,C.35建议将公共的基类析构函数设为虚拟:
C.35: 基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的
原因防止未定义的行为。如果析构函数是公共的,则调用代码可以尝试通过基类指针销毁派生类对象,如果基类的析构函数是非虚拟的,则结果未定义。如果析构函数是受保护的,那么调用代码就不能通过基类指针进行销毁,并且析构函数不需要是虚拟的;它确实需要受到保护,而不是私有,以便派生的析构函数可以调用它。通常,基类的编写者不知道销毁时要执行的适当操作。
[...]
注意虚函数定义了派生类的接口,无需查看派生类即可使用该接口。如果接口允许销毁,那么这样做应该是安全的。
[...]
例外我们可以想象一种情况,您可能需要一个受保护的虚拟析构函数:当一个派生类型的对象(并且只有这种类型)应该被允许通过指向基的指针来销毁另一个对象(而不是它自己)时。不过,我们在实践中还没有看到这样的案例。
执法
- 具有任何虚函数的类应该有一个析构函数,该析构函数要么是公共的和虚拟的,要么是受保护的和非虚拟的。
推荐阅读
- javascript - WebRTC 和 Node.JS:为什么无法显示远程视频
- python - 如何打印出字典中的值和项目,python
- sql - 正则表达式:给出两个匹配模式 ab{2,4}de 的例子
- python - Python从文件中提取最长的单词
- python - 如何在 SQLAlchemy 中查询您未创建的表(已在数据库中)
- python - 我想在函数中使用字典中的特定值 - Python
- python-3.x - 在 Python 中,类定义之外的方法与使用静态方法的方法之间有什么区别?
- c# - 使用 System.Text.Utf8JsonReader 读取数字
- python - Matplotlib - 使用填充可用空间的点创建散点图
- python - django 无法查看模板中的数据库项目