通过在构造函数体之前抛出异常来阻止构造

Preventing construction by throwing exception before constructor body

本文关键字:抛出异常 函数体      更新时间:2023-10-16

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);

右边两个表达式之间的逗号运算符依次计算表达式,丢弃除最后一个结果外的所有表达式。但我想知道的是,为什么你坚持在打开花括号之前这样做。在这里,您到底想实现什么,而将调用函数作为主体的第一件事是无法实现的?

请注意,如果您想尽早中止,那么在一个单独的基类中执行(您可以在那里使用私有继承(可能是最好的解决方案。这是唯一一个可以防止构建其他基础的解决方案,而你的解决方案没有。