Using Virtual Inheritance in Exception Types
Типы исключений должны использовать виртуальное наследование при получении из других типов исключений. Это понимание связано с Эндрю Кенигом. Использование виртуального наследования предотвращает проблемы двусмысленности в обработчике исключений:
#include <iostream>
struct my_exc1 : std::exception { char const* what() const throw(); };
struct my_exc2 : std::exception { char const* what() const throw(); };
struct your_exc3 : my_exc1, my_exc2 {};
int
main()
{
try { throw your_exc3(); }
catch(std::exception const& e) {}
catch(...) { std::cout << "whoops!" << std::endl; }
}
Вышеприведенная программа выводит «Whoops!», потому что преобразование в std:: Исключение неоднозначно.
Накладные расходы, связанные с виртуальным наследованием, всегда незначительны в контексте обработки исключений. Обратите внимание, что виртуальные базы инициализируются непосредственно конструктором самого производного типа (тип передается на бросок, в случае исключений). Однако, как правило, эта деталь не вызывает беспокойства при повышении:используется исключение, поскольку оно позволяет использовать типы исключений как тривиальные структуры без членов (нечего инициализировать). Видишь?Типы исключений в виде простых семантических тегов.