14

我知道拥有全局变量是不受欢迎的。但是在 Bjarne Stroustrup 所著的《C++ 编程语言》一书中,作者说“在从非本地静态对象的初始化程序抛出的情况下获得控制的唯一方法是 set_unexpected()”。它是如何完成的?

4

2 回答 2

8

我在其他一些论坛上发布了这个问题并得到了一些答案。

第一个是声明一个指针而不是拥有一个对象并在 main() 中初始化它

第二个是从另一个执行 set_terminate 的类派生类(其构造函数抛出异常),以便设置有意义的处理程序。第二个似乎在代码块 ide 中运行良好。

我用来测试的代码是:

void f()        //Unexpected exception handler
{
    cout<<"Terminate called "<<endl;
    exit (0);
}
class A         //Base class that performs set_unexpected
{
    terminate_handler h;
public:
    A()
    {
        h=set_terminate(f);
    }
    ~A()
    {
        set_terminate(h);
    }
};
class B:public A    //Derived class that throws unexpected_exception
{
public:
    B()
    {
        throw 1;
    }
};
B b;
int main()
{
}

程序显示消息:“Terminate called”并退出。

于 2012-12-12T13:10:34.900 回答
0

try/catch块在功能范围内或与功能范围一起。因此,全局对象不能驻留在try/catch范围内,因此您永远无法 捕获这些异常。

您可以探索特殊try/catch语法:

class Test {
public:
  Test ()
  try { throw 0; }
  catch(...) {}
};

这为处理此类异常提供了一些缓解。这是一个讨论相同问题的线程。
但是,您必须为您声明全局对象的每个类提供这样的语法

您可能想知道,如果您将try/catch其放入构造函数本身,有什么区别?好吧,如果一个全局对象初始化失败,那么内部try/catch会默默地吸收它,这很糟糕。
但是上面的语法会给你一个错误诊断的机会,然后再次抛出异常,这将终止程序。
有关更多详细信息,请参阅此线程

另一方面,std::unexpected()在不适合catch()抛出异常时调用。此功能是标准功能,但您可以使用std::set_unexpected().

于 2012-12-06T05:16:02.090 回答