异常在构造函数 try 块中捕获并处理,但仍会再次重新抛出

p3t*_*3t3 5 c++ inheritance exception try-catch

我试图更好地理解处理继承时的抛出-捕获机制。

我试图解决的问题是,如果在构造派生类时,首先构造的基类抛出异常,将会发生什么情况。

#include <stdexcept>
#include <iostream>

class Base
{
    public:
    Base()
    {
        throw  std::runtime_error("test");
    }
};


class Derived : public Base
{
    public:
    Derived() try : Base()
    {

    }
    catch (std::runtime_error& e)
    {
        std::cout <<  "Base throws an exception : " << e.what() << std::endl;
    }    
};


int main ()
{
   Derived temp;
   return (0);
}
Run Code Online (Sandbox Code Playgroud)

运行编译后的代码 (g++ std=11) 后,我收到以下消息:

基类抛出异常:测试

抛出“std::runtime_error”实例后调用终止

什么():测试

已中止(核心转储

我的 Base 抛出的异常被 Derived 构造函数的 try-catch 捕获,但由于某种原因,抛出的异常并没有停止在那里,为什么会这样,以及如何解决这个问题?

不管怎样,如果有更好的方法来处理派生类构造时基类可能抛出的异常,我愿意接受建议。

Sam*_*hik 8

C++ 的一个基本核心原则是,只有在对象的构造函数返回后,对象才会被完全构造。当执行进入类的构造函数时,类本身还没有构造。只有它的类成员是(以及任何基类)。只有当构造函数返回时,对象才被完全构造出来,你就有了一个完全煮熟的对象可以使用。

因此,构造函数中抛出异常意味着该对象尚未构造。句号。故事结局。这就是她写的全部。这条规则没有例外(双关语)。

现在,当您捕获从基类的构造函数抛出的异常时,这意味着什么?好吧,您可以这样做,但这并不能改变抛出异常并且未构造基类的事实。这意味着无法构造派生类。您不能期望执行到达异常处理程序的末尾,然后返回到父级,就好像该类已完全构建且没有错误一样。

这不会只是发生。不知何故,你不能最终导致基类没有被构造,但派生类却被构造。C++ 不是这样工作的。

当您从基类捕获异常时,您只有两个选择:

1)你的异常处理程序可以在完成它想做的任何事情之后重新抛出它自己的异常。

2) 否则,如果异常处理程序返回时没有抛出自己的异常,C++ 将为您重新抛出异常。