【问题标题】:Try catch syntax constructor尝试 catch 语法构造函数
【发布时间】:2018-08-24 01:10:29
【问题描述】:

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;
}

【问题讨论】:

    标签: c++ exception


    【解决方案1】:

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

    毕竟,超类并没有被构造出来。它抛出了一个异常。所以你不能真正继续你的快乐方式,在子类的构造函数中,然后最终得到一个构造好的子类,但得到一个没有构造的超类。这没有任何意义。

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

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

    这确实是函数尝试块的主要增值:一个方便的地方记录“嘿,这个函数抛出了异常”,它包含了整个函数,一个记录这种事情的地方,但是不影响普通异常处理。

    【讨论】:

      【解决方案2】:
      构造函数中的

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

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

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

      之所以会这样,是因为如果基类或者任何成员构造函数抛出异常,那么整个对象的构造就失败了,没有办法修复,所以只好抛出异常。

      上面有个GOTW,底线是

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

      所以,是的,您的最后一个代码示例非常好。

      【讨论】:

      • 假设你是谷歌,有不使用异常的政策,你找到了一个很酷的库,但是你想从 throws 继承的类(仅在构造函数中,在其他任何地方都没有)。如果从它继承,每个使用派生类的人每次都必须使用 try/catch。在那种情况下你会怎么做?似乎唯一的答案是:使用另一个库,只是由于构造函数......
      • @Phantom 或不继承它,将指向它的指针设为成员并在构造函数主体中初始化它。但我相信在谷歌他们无论如何都不会允许你使用那个库。
      猜你喜欢
      • 2015-10-07
      • 1970-01-01
      • 1970-01-01
      • 2011-04-22
      • 2015-09-13
      • 2020-06-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多