Виртуальное наследование необходимо для исключений? - PullRequest
10 голосов
/ 03 мая 2011

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

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

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

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

Ответы [ 5 ]

17 голосов
/ 03 мая 2011

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


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

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

#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 :: exception является неоднозначным.

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

1 голос
/ 25 октября 2011

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

1 голос
/ 03 мая 2011

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

0 голосов
/ 29 октября 2011

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

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

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

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

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

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

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

0 голосов
/ 03 мая 2011

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

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