尝试使用catch语法构造函数

时间:2016-03-29 00:57:52

标签: c++ exception

http://ideone.com/UtVzxw

struct base
{
    base() { throw std::exception(); }
};

struct derived : public base
{
    derived() try : base()  { }

    catch (std::exception& e)
    {
        std::cout << "exception handled" << std::endl;
    }
};

int main()
{
    derived a; // My app crashes.
    return 0;
}

不是我的应用写了“处理异常”并继续运行?

我发现的唯一解决方案是在try / catch块中包围“a”的构造。但是,如果我这样做,那么首先在构造函数中使用try / catch有什么意义呢?我猜也许它的用途是清理可能已分配的成员变量?因为析构函数没有被调用?

以下工作,但处理异常2次。

struct base
{
    base() { throw std::exception(); }
};

struct derived : public base
{
    derived() try : base() { }

    catch(std::exception& e)
    {
      std::cout << "exception 1" << std::endl;
    }
};

int main()
{
    // This works fine.
    try {
       derived a;
    }
    catch(std::exception& e)
    {
      std::cout << "exception 2" << std::endl;
    }
    return 0;
}

我只是想问自己为什么我不应该简单地为构造函数躲避try / catch语法并写下这个:

struct base
{
    base() { throw std::exception(); }
};

struct derived : public base
{
    derived() : base() { }
};

int main()
{
    // This works fine.
    try {
       derived a;
    }
    catch(std::exception& e)
    {
      std::cout << "exception handled" << std::endl;
    }
    return 0;
}

2 个答案:

答案 0 :(得分:9)

构造函数中的

function-try-block 不会阻止抛出异常。这是C ++标准草案N4140的摘录,[除了.handle]:

  

14如果返回语句出现在构造函数的 function-try-block 的处理程序中,则该程序格式错误。

     

15如果控件到达构造函数或析构函数的 function-try-block 的处理程序的末尾,则会重新抛出当前处理的异常。否则,......

原因是如果基类或任何成员构造函数抛出异常,则整个对象的构造失败,并且无法修复它,因此必须抛出异常。 / p>

此处有一个GOTW,底线是

  

构造函数function-try-block处理程序只有一个目的 - 转换异常。 (也许是为了记录或其他一些副作用。)它们对任何其他目的都没用。

所以,是的,您的上一个代码示例完全正常。

答案 1 :(得分:4)

围绕超类的构造函数包装try / catch可以捕获在超类的构造函数中抛出的异常;但是,当catch块结束时,异常会自动重新抛出,异常继续传播。

毕竟,超类没有构建。它引发了一个例外。所以你不能真正继续你的快乐方式,在子类的构造函数中,然后最终得到一个构造的子类,但是有一个没有构造的超类。这毫无意义。

来自http://en.cppreference.com/w/cpp/language/function-try-block

  

function-try-blocks的主要目的是记录或修改,和   然后重新抛出从成员初始化列表中抛出的异常   构造函数。它们很少与破坏者或常规使用   功能

这实际上是function-try块的主要增值:一个方便的记录位置&#34;嘿,这个函数引发了一个异常&#34;,它包含了整个函数,一个单独的地方来记录这种一件事,但不影响普通的异常处理。