类层次中的C++异常处理

7
在异常类的层级结构中,应按照从最派生到基类的顺序排列catch语句,以允许捕获异常类层级中多个类的异常。
3个回答

5
最具体的排在最前面。处理程序按照它们出现的顺序进行匹配,因此您希望最具体的处理程序排在最前面。

这还取决于继承类型。 - iammilind

1

我的答案是基于Linux编译器,但希望对所有编译器都适用。catch的顺序取决于两个因素:

(1) 先来先选;如果基类出现在派生类之前,则会选择基类。有些编译器会警告此情况,有些则不会;

(2) 继承类型;即公共或非公共(私有/保护)。

struct B {};
struct D : B {};
struct DD : D {};

int main()
{
  for(int i = 0; i < 3; i++)
  {
  try
  {
    switch(i)
    {
    case 0: throw new B;
    case 1: throw new D;
    case 2: throw new DD;
    }
  }
  catch(B *o) { cout<<"B* caught\n"; }
  catch(D *o) { cout<<"D* caught\n"; }
  catch(DD *o) { cout<<"DD* caught\n"; }
  }
}

(1)在上面的代码中,它总是捕获B。如果您更改为捕获DD、D、B的顺序,则会按照您的期望给出派生类。

(2)现在将“struct”替换为“class”,或将继承更改为private/protected;在上述代码中,无论顺序如何,catches都将匹配throw的类型。它将非常严格,即使您删除Derived类的任何catch,也不会被Base类捕获。


2
请不要再这样做了。不要使用throw new Foo;或者catch (Foo*)。通过值抛出并通过(const)引用捕获(throw Foo();catch (Foo const&))。 - Max Truxa

0

正确的顺序应该是最派生的先。处理程序必须按照从最派生类到基类的顺序排列。
这里是一个代码示例:

#include <iostream>

using namespace std;

class MyException
{
    public: 
    MyException(int value):mValue(value)
    {
    }
    int mValue;
};

class MyDerivedException: public MyException
{
    public: 
    MyDerivedException(int value, int anotherValue):MyException(value),mAnotherValue(anotherValue)
    {
    }
    int mValue;
    int mAnotherValue;
};

void doSomething()
{

    //Lot of Interesting stuff

    //Exception condition
    throw MyDerivedException(10,20);
}

int main()
{
    try
    {
        doSomething();
    }
    catch(MyDerivedException &exception)
    {
        cout<<"\nCaught Derived Class Exception\n";
    }
    catch(MyException &exception)
    {
        cout<<"\nCaught Base Class Exception\n";
    }
    return 0;
}

在上面的例子中,处理程序按照派生类(MyDerivedException)和基类(MyException)的顺序排序。如果这些处理程序的顺序被颠倒,那么基类处理程序将捕获所有抛出的异常(即使它们是派生类的异常)。这是因为可以始终将派生类对象/指针分配给没有任何类型转换或显式处理的基类对象/指针。
希望对你有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接