Обработка исключений в C ++ в иерархиях классов - PullRequest
6 голосов
/ 07 апреля 2011

В иерархии классов исключений, каков правильный порядок операторов catch, позволяющий перехватывать исключения более чем одного класса из иерархии классов исключений?

Является ли он наиболее производным длябаза или база для большинства производных?

Ответы [ 3 ]

4 голосов
/ 07 апреля 2011

Большинство выводится первым. Обработчики подбираются в том порядке, в котором они появляются, поэтому сначала вы хотите указать наиболее конкретные из них.

1 голос
/ 07 апреля 2011

Мой ответ в соответствии с компилятором Linux, и, надеюсь, это должно быть верно для всех.Порядок вылова зависит от 2 факторов:

(1) First First First First Choice ;Если базовый класс появится раньше производного, ему будет предоставлен выбор.Некоторые компиляторы предупреждают об этом, некоторые - нет;

(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;В приведенном выше коде, независимо от порядка, уловы будут соответствовать типу броска.Это будет настолько строго, что даже если вы удалите какой-либо из уловов класса Derived, он не будет пойман базовым классом.

0 голосов
/ 07 апреля 2011

Правильный порядок должен быть наиболее производным первым. Обработчики должны быть в порядке от большинства производных до базового класса.
Вот пример кода:

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

В приведенном выше примере обработчики упорядочены как класс Derived (MyDerivedException), а затем базовый класс (MyException). Если порядок этих обработчиков обратный, то обработчик базового класса будет перехватывать все сгенерированные исключения (даже если они относятся к классу Derived). Это потому, что всегда можно присвоить объект / указатель производного класса объекту / указателю базового класса без какой-либо типизации или явной обработки.
Hth.

...