зачем пытаться ... ловить требует ТОЧНО брошенного типа - PullRequest
8 голосов
/ 27 сентября 2011

Я могу это сделать, нет проблем:

long lngval = 3L;
int i = lngval;

но если я попробую это:

try {
  throw 3L;
}

catch(int i) {
  cout << "caught " << i << endl;
}

Я получаю необработанное исключение.

Это кажется противоречивым. в чем причина отсутствия преобразования типов в этом случае?

Ответы [ 5 ]

7 голосов
/ 27 сентября 2011

В первом случае компилятор может точно сказать, что вы хотите сделать: преобразовать long в int. Во втором случае компилятор должен предположить, что у вас может быть такая конструкция:

try {
  try {
    throw 3L;
  }
  catch (int i) { /* P */ }
}
catch (long l) { /* Q */ }

Идея состоит в том, что компилятор никогда не узнает, может ли catch (long l) скрываться за пределами текущего контекста, поэтому никогда не безопасно просто выбрать первое возможное преобразование.

По этой же причине при генерировании исключений часто используется иерархия классов, а не случайные типы, такие как int или long: это позволяет легко добавлять более или менее спецификации в обработчики исключений таким образом, Компилятор может быть уверен в ваших намерениях (через отношения is-a ).

4 голосов
/ 27 сентября 2011

catch действительно не обязательно нужен точный тип.

Обычной и эффективной практикой является использование исключений, полученных из std::exception (встречается в <stdexcept>). Причина заключается в том, что вы можете полиморфно ловить, то есть вам не нужно знать точный тип (см. Также Разница: std :: runtime_error vs std :: exception () ) и что у нас есть соглашение, чтобы справиться с этим.

Либо вы используете одну из тех, что предусмотрены стандартом (например, std::range_error), либо, если вас не устраивает [достаточно], специализация std::exception:

#include <stdexcept>

class moores_law_stopped : public std::exception {
public:
    virtual ~moores_law_stopped() throw() {} 
    virtual const char *what() const throw() { 
        return "moores law stopped. duck under your table.";
    }
};



#include <iostream>
int main () {
    try {
        throw moores_law_stopped();
    } catch (std::exception const &e) {
        std::cerr << "oh oh: " << e.what() << std::endl;
    }
}

Выход:

oh oh: moores law stopped. duck under your table.

Соглашение заключается в отлове по ссылке или константной ссылке, так что вы получаете полиморфное поведение, не опасаясь нарезки объектов .

1 голос
/ 27 сентября 2011

Вы также можете throw 3; - без проблем.

int и long - это разные типы. Преимущество обработки исключений заключается в том, что вы можете отличать их от других типов, не обращая внимания на их тип (один центральный блок try может обрабатывать исключения разных типов из разных мест / блок try может обрабатывать только некоторые виды исключений, позволяя другим распространяться).

Также рекомендуется выбросить одно из стандартных исключений или извлечь класс из одного из них. Тогда вы можете просто catch (const std::exception&), если вы просто хотите обработать исключение и не заботиться о конкретном типе.

1 голос
/ 27 сентября 2011

Оператор catch перехватывает объект (или скалярную переменную в ваших случаях) по его типу, поэтому, если тип не соответствует, он переходит к следующему оператору catch (если он есть) или к получателю исключения по умолчанию.

В вашем случае у вас может быть второй оператор catch, перехватывающий long, и, возможно, где-то еще, так что ваш оператор catch не будет ничего ловить.

Чтобы перехватить любое исключение, просто используйте catch ()}:)

Один совет, лучше использовать класс исключений или создать подкласс для собственных нужд:)

0 голосов
/ 27 сентября 2011

Вы можете поймать несколько типов в одном блоке try-catch. Чтобы компилятор знал, к какому блоку catch нужно добавить, он должен иметь возможность точно соответствовать типу. Или он может иметь блок по умолчанию - catch (...) {}, но вы не сможете получить значение, выброшенное в этом случае.

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