c++ - 抛出数据成员的析构函数
问题描述
我有一个类,它包含一个析构函数可以抛出的对象(它实际上是一个 tbb::task_group,但为了简单起见,我在这里将其命名为 MyObject)。
代码是这样的:
#include <stdexcept>
class MyObject {
public:
MyObject() {}
~MyObject() noexcept(false) {}
};
class A {
public:
A() {}
virtual ~A() {}
};
class B : public A {
public:
B() : A() {}
~B() {}
private:
MyObject _object;
};
并且编译器会引发以下错误:
覆盖函数的异常规范比基础版本更宽松
我不喜欢在整个代码中传播 noexcept(false) 的想法,所以我正在考虑使用指向 MyObject 的原始指针,并在析构函数之外删除它们(例如在 Close 函数中)。
处理这种情况的最佳方法是什么?
解决方案
noexpect(true)
默认情况下,除非明确指定,否则析构函数是默认的,或者除非基类或成员的析构函数可以抛出。后者是你的情况。之后,它是函数签名之间的简单不匹配。
virtual ~A() {}
因而实际上是virtual ~A() noexcept {}
哪一个不匹配virtual ~B() noexcept(false) {}
。
你有两个解决方案:
- 显式标记
~B
为noexcept(true)
,但如果~MyObject
抛出,程序将在~B
' 边界处终止。 - 马克
~A
也noexcept(false)
,
从析构函数中抛出是一个非常糟糕的主意。抛出对象不能被破坏的信号,这真的是你的代码中发生的事情吗?仅当正确的响应是立即终止程序时才抛出,因为如果将析构函数作为堆栈展开的一部分调用,就会发生这种情况。在这种情况下,不会调用其他析构函数,这可能会比不死对象造成更大的伤害。
如果您真的想要安全并且不关心抛出的异常,您可以unique_ptr
使用吸收析构函数将成员包装在 a 中:
class B : public A {
public:
B() : A(), _object{new MyObject,deleter} {}
~B() noexcept(true) {}
private:
constexpr static auto deleter = [](MyObject* obj){ try { delete obj;}catch(...){};};
std::unique_ptr<MyObject,decltype(deleter)> _object;
};
推荐阅读
- mysql - 使用今天添加的转储文件将 MySQL 恢复到特定的先前日期
- postgresql - 如何通过对象的层次结构(?)快速获取标签?
- android - TGeocoder 只显示第一个标记的地址
- python - 使用 go.Scatter3d 和 Dash 进行 3D 聚类
- python - 如何根据python中的if语句跳到循环的下一次迭代?
- flutter - 是否可以禁用在颤动的可重新排序列表视图中重新排序单个项目?
- sqlite - sqlite3 select records from multiple tables
- android - 将 ImageVector 从 Jetpack Compose 转换为 BitmapDescriptor
- python - 如何找到一个数组的平均值并将其与其对应的名称固定在另一个数组中
- javascript - 在 django modelform 属性上传递 url 参数