Требуется ли Virtual Inheritance для исключений?

Я понимаю необходимость виртуального наследования при использовании множественного наследования - он решает проблему Dreaded Diamond.

Но что, если я не использую множественное наследование? Есть ли необходимость в виртуальном наследовании вообще?

Мне кажется, что я слышал, что это важно для исключений (выкидывать производный класс, catch по ссылке базового класса). Но разве виртуальные деструкторы не должны быть достаточными для этого?

Я попытался найти ссылочную страницу, которую я когда-то видел, но я не могу ее найти.

Ответ 1

Вероятно, вы думаете об этом Boost.Exception guideline, который я скопирую здесь для полноты:


Использование виртуального наследования в типах исключений

Типы исключений должны использовать виртуальное наследование при получении из других типов исключений. Это понимание было вызвано Эндрю Кенигом. Использование виртуального наследования предотвращает проблемы двусмысленности в обработчике исключений:

#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; }
    }

Программа выше выводит "возглашает!" потому что преобразование в std:: exception неоднозначно.

Накладные расходы, введенные виртуальным наследованием, всегда незначительны в контексте обработки исключений. Обратите внимание, что виртуальные базы инициализируются непосредственно конструктором самого производного типа (тип, переданный в оператор throw, в случае исключений.) Однако обычно эта деталь не вызывает беспокойства, когда boost:: exception, поскольку он позволяет типам исключений быть тривиальными структурами без членов (там ничего не инициализировать.) См. типы исключений в виде простых семантических тегов.

Ответ 2

Нет, это не нужно, кроме как решить проблему с алмазом. Вы должны воображать вещи!

Ответ 3

Да, если ваши классы исключений связаны с множественным наследованием.

Ответ 4

Единственная стоимость виртуального наследования - это vtable, которая не является значительной стоимостью. Использование виртуального наследования означает, что позже, после того, как люди наследуют от различных вещей, проблема двойного алмаза не будет неожиданно заводить их уродливую голову. Это просто означает, что ваш класс сделает хороший базовый класс.

Ответ 5

Я понимаю необходимость виртуального наследования при использовании множественного наследования - он решает проблему Dreaded Diamond.

Но что, если я не использую множественное наследование?

Вопрос (в основном риторический): Как вы узнали, что МИ никогда не будет использоваться?

Ответ: Вы не можете этого знать. (Пока вы не докажете это.)

Мне кажется, что я слышал, что это важно для исключений (выкидывать производный класс, catch по ссылке базового класса). Но разве виртуальные деструкторы не должны быть достаточными для этого?

Вопрос (риторический): Зачем нужен виртуальный деструктор?

Ответ: Это не так.