通过在构造函数体之前抛出异常来阻止构造
Preventing construction by throwing exception before constructor body
C++
我希望一个类在其构造函数主体的开头大括号{
之前使用自己的成员函数来阻止构造,从而将异常throw
作为异常。我定义了一个成员函数,其目的只是无条件地将throw
作为异常,使用任意选择的非void
返回类型和类型与该返回类型匹配的伪数据成员,这样我就可以通过调用构造函数初始值设定项列表中的所述成员函数来构造该数据成员,从而触发throw
。这很有效,但并不优雅,因为在非toy类中,伪变量除了有一个运行成员函数的借口之外,没有其他用途,而成员函数的非void
返回类型除了有一种由相同类型的伪数据成员的构造函数调用的借口之外没有其他用途。
这个玩具可编译但并不优雅:
class Toy
{
public:
Toy() : dummy(preventer()) {}
private:
int dummy;
int preventer() {throw -1; return 0;}
};
#include <iostream>
int main()
{
try
{
Toy t;
}
catch (const int& e)
{
std::cout << "caught the exceptionn";
}
return 0;
}
控制台输出:
caught the exception
如果没有伪变量,有没有办法在构造函数体的开头大括号{
之前抛出异常?
是的,您可以使用基类而不是数据成员,然后调用基类的构造函数。
请注意,GNU调试器gdb
的旧版本(几年前(无法破解此类异常。
然而,它可以与Visual C++配合使用,我相信也可以与GNU工具链的现代版本配合使用。
您可以避免函数的伪返回值,如下所示:
bool called = (function(), true);
右边两个表达式之间的逗号运算符依次计算表达式,丢弃除最后一个结果外的所有表达式。但我想知道的是,为什么你坚持在打开花括号之前这样做。在这里,您到底想实现什么,而将调用函数作为主体的第一件事是无法实现的?
请注意,如果您想尽早中止,那么在一个单独的基类中执行(您可以在那里使用私有继承(可能是最好的解决方案。这是唯一一个可以防止构建其他基础的解决方案,而你的解决方案没有。
相关文章:
- 从构造函数抛出异常时如何克服内存泄漏
- 函数如何通知用户它基于函数原型抛出异常?
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- 为什么访问模板化变体作为返回值抛出异常
- std::vector 默认构造函数可以抛出异常吗?
- std:任何抛出异常解析函数类型
- 从成员构造函数(Brace Initializer vs Initializer列表)抛出异常
- 跨dll边界向构造函数抛出异常
- 在QT中创建我自己的异常并在函数中抛出异常
- 是否可以对构造函数抛出异常的对象进行异常处理,该对象的异常处理接近其基于堆栈的代码创建
- 奇怪的格式用于从构造函数中抛出异常
- std::map at 函数总是抛出异常
- 为什么当我在使用空 throw() 说明符指定的函数中抛出异常时没有调用 std::unexpected()
- 如果构造函数抛出异常,如何删除对象
- 如果文件在构造函数中不存在,则抛出异常,并在 main() 中创建对象时尝试/捕获它,如果好 - 开始使用该对象
- 从几个函数调用中抛出异常的方法,一直返回到main
- std::regex构造函数抛出异常
- 抛出异常并返回函数的结果
- 正在从vtable的析构函数安全抛出异常
- 通过在构造函数体之前抛出异常来阻止构造