Спецификация исключения при переопределении виртуальной функции - PullRequest
6 голосов
/ 05 марта 2010

Рассмотрим следующий код:


class A
{
public:
    virtual void f() throw ( int ) { }
};

class B: public A
{
public:
    void f() throw ( int, double ) { }
};

При компиляции он говорит, что производный класс B имеет более слабый спецификатор броска по сравнению с A. В чем важность этого?Если мы попытаемся обменять их спецификацию исключений, такую, что A :: f () выдает int и double, а B :: f () выдает только int, ошибка не появляется.

Ответы [ 2 ]

13 голосов
/ 05 марта 2010
  1. Не используйте спецификации исключений в C ++. Это очень нелогично по сравнению, скажем, с Java.
  2. Наличие более широкой спецификации в производном классе ломает LSP(Принцип подстановки Лискова).

Чтобы развернуть точку 2: абоненты A ожидают, что только int выйдет, но если вы используете B (что, потому что это публично)полученный из A, также означает, что его можно использовать как A), неожиданно может также выйти double, и это нарушит контракт A (который будет брошен только int).

1 голос
/ 05 марта 2010

Ваш B нарушает принцип замещения Лискова - например:

void foo(A* a) throw() // ie I will not throw
{
  try
  {
     a->f();
  }
  catch(int)
  {}
}

Это действительно в соответствии с интерфейсом для A;в частности, мы не ожидаем двойного броска.Но подумайте, если бы мы звонили

foo(new B)

с интерфейсом, который вы описали, и

B::f()
бросили бы двойку.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...