Как вызвать исключение по типу времени выполнения? - PullRequest
4 голосов
/ 24 марта 2011

Я хочу вызвать функцию, которая может вызвать исключение.Если оно вызывает исключение, я хочу поймать его и передать объект исключения в функцию-обработчик.Реализация функции-обработчика по умолчанию - просто выбросить исключение.Вот сокращенный код, иллюстрирующий проблему:

struct base_exception : exception {
  char const* what() const throw() { return "base_exception"; }
};

struct derived_exception : base_exception {
  char const* what() const throw() { return "derived_exception"; }
};

void exception_handler( base_exception const &e ) {
  throw e; // always throws a base_exception object even if e is a derived_exception
}

int main() {
  try {
    throw derived_exception();
  }
  catch ( base_exception const &e ) {
    try {
      cout << e.what() << endl; // prints "derived_exception" as expected
      exception_handler( e );
    }
    catch ( base_exception const &e ) {
      cout << e.what() << endl; // prints "base_exception" due to object slicing
    }
  }
}

Однако throw e в exception_handler() создает копию статического типа исключения, то есть base_exception.Как я могу заставить exception_handler() выдать фактическое исключение, имеющее правильный тип времени выполнения derived_exception?Или как мне изменить дизайн, чтобы получить то, что я хочу?

Ответы [ 4 ]

3 голосов
/ 23 марта 2012

Вы можете поместить виртуальную функцию throw_me в базовый класс исключений, и каждый производный класс может переопределить ее. Производные классы могут генерировать правильный наиболее производный тип, без нарезки. Несмотря на то, что функция имеет одинаковое определение в каждом классе, они не одинаковы - тип *this отличается в каждом случае.

struct base_exception : exception
{
  char const* what() const throw() { return "base_exception"; }
  virtual void throw_me() const { throw *this; }
};

struct derived_exception : base_exception
{
  char const* what() const throw() { return "derived_exception"; }
  virtual void throw_me() const { throw *this; }
};

void exception_handler( base_exception const &e ) {
  e.throw_me();
} 
2 голосов
/ 24 марта 2011

Вы можете использовать throw;, чтобы повторно выдать исключение, которое было перехвачено. Вы также можете использовать шаблон.

template<typename T> void rethrow(const T& t) { throw t; }

0 голосов
/ 24 марта 2011

То, что вы ищете, называется «распространением» исключения.Для этого необходимо использовать ключевое слово throw без параметров внутри блока catch.Он не будет копировать исключение, и исключение будет перехвачено следующим блоком catch на его пути или заставит вашу программу прерваться, если она не перехватится снова.

0 голосов
/ 24 марта 2011

Бросок по значению, улов по ссылке .Это избавит вас от многих головных болей.

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