Ответ 1
Захват заброшенных исключений сильно отличается от передачи аргументов в функции. Есть сходства, но есть и тонкие различия.
3 основных отличия:
- исключения всегда копируются хотя бы один раз (этого вообще не избежать)
-
catch
статьи рассматриваются в том порядке, в котором они объявлены (не подходят) - они подвержены меньшему количеству преобразований типов:
- наложения, основанные на наследовании,
- преобразование из типизированного в нетипизированный указатель (
const void*
ловит любой указатель)
Любое другое преобразование не разрешено (например, от int
до double
или неявный const char*
до string
- ваш пример).
Относительно вашего вопроса в комментарии Предположим, что существует иерархия:
class Base {};
class Derived: public Base {};
class Base2 {};
class Leaf: public Derived, public Base2 {};
Теперь, в зависимости от порядка предложений catch
, будет выполнен соответствующий блок.
try {
cout << "Trying ..." << endl;
throw Leaf();
} catch (Base& b) {
cout << "In Base&";
} catch (Base2& m) {
cout << "In Base2&"; //unreachable due to Base&
} catch (Derived& d) {
cout << "In Derived&"; // unreachable due to Base& and Base2&
}
Если вы переключаете Base
и Base2
порядок улова, вы заметите другое поведение.
Если Leaf
наследуется в частном порядке от Base2
, то catch Base2&
будет недоступен независимо от того, где он был помещен (при условии, что мы выбрали Leaf
)
Как правило, это просто: порядок.