为什么std :: exception在std :: bad_alloc之前捕获我的异常?

时间:2018-02-05 09:49:03

标签: c++ exception

问题:我正在使用std :: exception和std :: bad_alloc来捕获异常。我正在使用的try catch的顺序有问题。我附上了示例代码以供参考。

预期:如果我的错误是bad_alloc,则抛出bad_alloc异常。

观察:我的错误是bad_alloc,但抛出了异常。

示例代码

#include "stdafx.h"
#include <iostream>
#include <exception>

using namespace std;

void goesWrong()
{
    bool error1Detected = true;
    bool error2Detected = false;

    if (error1Detected)
    {
        throw bad_alloc();
    }

    if (error2Detected)
    {
         throw exception();
    }
}

int main()
{
    try
    {
        goesWrong();
    }
    catch (exception &e)
    {
        cout << "Catching exception: " << e.what() << endl;
    } 
    catch (bad_alloc &e)
    {
        cout << "Catching bad_alloc: " << e.what() << endl;
    }

    return 0;
}

2 个答案:

答案 0 :(得分:23)

关于它们的继承关系,您必须以相反的顺序放置异常。 std :: exception std :: bad_alloc 的父类,这就是之前在catch列表中找到它的原因。因此,您必须将代码转换为:

   try {
      goesWrong();
   }
   catch (bad_alloc &e)
   {
      cout << "Catching bad_alloc: " << e.what() << endl;
   }
   catch (exception &e)
   {
      cout << "Catching exception: " << e.what() << endl;
   }

你不仅限于 catch 对象:你可以抛出整数,字符......无论如何。在这种情况下,catch(...)是唯一可以捕获它们的安全方法。

也就是说,使用标准类库中的对象是建议的方法。在这种情况下,由于 std :: exception 是所有(标准)异常的基类,它将捕获所有可能抛出的异常。

您可以创建自己的异常类,从 std :: exception std :: runtime_error 派生它们,例如,我个人的选择。

希望这有帮助。

答案 1 :(得分:0)

在C ++中,将处理程序与异常匹配时会考虑列出异常处理程序的顺序。即使在列表中有更好的匹配,也将调用可以处理异常的第一个处理程序。这与Java或C#不同,后者只调用最佳匹配(并且编译器会强制您将其放在列表的顶部)。

当通过引用传递异常时,多态性适用;这意味着可以将子类传递给期望其父类的处理程序。由于 std :: bad_alloc std :: exception 的子类,因此它将由第一个catch块处理。

要获得预期的行为,请将catch块反过来:

$postall = $user->posts()->with('comments', 'tags')->where('status', 1)->latest()->get();

这样, std :: bad_alloc 将与第一个处理程序匹配,而 std :: exception 及其所有其他子类将匹配第二个。