如何捕获从类的全局实例的构造函数抛出的异常?

时间:2012-12-04 04:40:45

标签: c++ exception-handling constructor global

我知道拥有全局变量并不受欢迎。但在本书中,作者Bjarne Stroustrup撰写的C ++编程语言称,“在非本地静态对象的初始化器抛出的情况下获得控制权的唯一方法是set_unexpected()”。怎么做?

2 个答案:

答案 0 :(得分:7)

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

首先是声明一个指针而不是一个对象,并在main()

中初始化它

第二个是从另一个执行set_terminate的类派生类(其构造函数抛出异常),以便设置一个有意义的处理程序。第二个似乎在codeblocks 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()
{
}

程序显示消息:“终止被叫”并退出。

答案 1 :(得分:0)

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

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

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

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

您可能想知道如果将try/catch放在构造函数本身中有什么区别?好吧,如果一个全局对象无法初始化,那么内部try/catch将默默吸收它,这是不好的。
但是上面的语法将为您提供错误诊断的机会,然后再次重新抛出将终止程序的异常 See this thread了解更多详情。

另一方面,如果抛出的异常没有合适的catch(),则会调用std::unexpected()。此功能是标准功能,但您可以使用std::set_unexpected()配置自己的功能。