【问题标题】:How can I catch exceptions thrown from constructor of a global instance of a class?如何捕获从类的全局实例的构造函数抛出的异常?
【发布时间】:2012-11-21 16:23:17
【问题描述】:

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

【问题讨论】:

  • 这是一个很好的问题,不敢相信它已经开放了 2 天而没有任何评论!
  • @j_random_hacker,一旦它从newest 的顶部掉下来,它(通常)和丢失一样好
  • 我想如果你在主函数之外抛出一个对象,最好使用 set_terminate 而不是 set_unexpected。因为 terminate() 是在 try/catch 块之外抛出异常时调用的函数,除非您在不在此函数异常规范列表中的类型的函数内抛出 excption 对象。

标签: c++ exception-handling constructor global


【解决方案1】:

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

第一个是声明一个指针而不是拥有一个对象并在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”并退出。

【讨论】:

  • 第一个解决方案的优点是实际上有机会处理异常并做一些有用的事情。通常,您仍然只会打印一条消息并终止进程,但有时可以从异常中恢复。 OTOH,第二个解决方案是错误的,它应该使用set_terminateunexpected not 处理未捕获的异常,它处理不符合函数异常规范的异常!)。但即便如此,一旦在终止函数中,除了终止进程,你还能做什么呢?没有地方可以返回。
  • 我同意上述评论,当您从 try/catch 块中抛出异常时,通常终止函数是被调用的函数,除非您在类型为的函数中抛出异常对象不在功能异常指定列表中。
  • @Damon 。是的。我对这个问题的答复也指出了同样的事实。唯一可以执行的是一些清理活动。感谢您指出 set_terminate 方法。我已经根据 set_terminate 对代码进行了更改。如果有任何错误,请帮助我
【解决方案2】:

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

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

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

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

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

另一方面,std::unexpected() 在没有合适的catch() 用于抛出异常时被调用。此功能是标准功能,您可以使用std::set_unexpected()自行配置。

【讨论】:

  • 但是,“在从非本地静态对象的初始化程序抛出的情况下获得控制权的唯一方法是 set_unexpected()”.. 这句话是什么意思?
  • @sajas,我不确定这是什么意思。即使尝试在异常之前设置处理程序也无济于事。可能我们需要更深入地研究它。需要看看这句话是在什么背景下写的。
  • 我在 Bjarne Stroustrup 的《C++ 编程语言第三版》一书中看到了它。它在第 14.7 节未捕获的异常,倒数第二段中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
相关资源
最近更新 更多