【发布时间】:2021-11-19 09:36:25
【问题描述】:
我有一个类,它包含一个析构函数可以抛出的对象(它实际上是一个 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 函数中)。
处理这种情况的最佳方法是什么?
【问题讨论】:
-
我发现在 B 类中使用 std::unique_ptr
可以消除错误。根据对这个问题的回答,不确定这是一个好主意:stackoverflow.com/questions/37788282/… -
从析构函数中抛出异常并不是一个好主意。请注意,如果确实发生异常,添加 noexcept 将具有终止程序的效果。你可以做的是在你的析构函数中使用 try/catch 块来处理出错的事情。但一般来说,不要扔析构函数
-
可能抛出的析构函数通常是个坏主意:C++ FAQ: How can I handle a destructor that fails? 和 Andrzej's C++ blog: Destructors that throw。您仍然可以选择将所有内容放在
try catch块中,或者至少保留析构函数 noexcept(如果所有这些都调用了异常,它可能会调用std::terminate())。关于成员和基类的析构函数......它们也应该是 noexcept 。 ;-) -
抛出的析构函数实际上来自外部库(更具体地说,是 tbb::task_group,正如我在开头提到的那样)。
-
unique_ptr的@Uraza析构函数要求deleter的应用不抛出:en.cppreference.com/w/cpp/memory/unique_ptr/~unique_ptr。您需要使用带有异常忽略的自定义删除器。或者,使用原始指针。或者,仅使用具有手动生命周期管理的对齐存储(如果您想避免动态分配的过时,这里可能不是这种情况)。
标签: c++