#c #virtual-inheritance
#c #виртуальное наследование
Вопрос:
Рассмотрим следующую программу:
#include <iostream>
#include <string>
class B
{
public:
int n;
B() : n(0) {}
B(int m) : n(m) {}
};
class D1 : virtual public B
{
public:
int a;
D1() : a(0) {}
D1(int m) : a(m) {}
};
class D2 : public D1
{
public:
int d;
D2() : d(0) {}
D2(int m) : d(m) {}
D2(int j, int k) : d(j), D1(k) {}
D2(int i, int j, int k) : d(i), D1(j), B(k) {} //Without virtual inheritance,
//must add new constructor to D1.
};
int main()
{
std::string s;
D2 d2(0, 1, 2);
std::cout << "d2.n = " << d2.n << "n";
std::cout << "d2.a = " << d2.a << "n";
std::cout << "d2.d = " << d2.d << "n";
std::cout << "Press ENTER to exit.n";
getline(std::cin, s);
}
Наследование D1 виртуально от B позволяет мне вызывать конструктор B из конструктора D2, перепрыгивая через класс D1.
Может ли это использование виртуального наследования отдельно от проблемы наследования алмаза вызывать неопределенное поведение или другой вред?
Я никогда не видел, чтобы виртуальное наследование использовалось, кроме как для решения проблемы наследования алмазов.
Комментарии:
1. Когда вы говорите «перепрыгивание через класс D1», вы говорите о порядке инициализации? Я подозреваю, что ответ, который вы ищете, зависит от того, что вы подразумеваете под «перепрыгиванием». Построение a
D2
построит aB
, независимо от того, существует ли виртуальное наследование.2. Нет, я просто имею в виду, что мне не нужно добавлять в D1 конструктор с двумя аргументами, который вызывал бы конструктор D2 вместо прямого вызова конструктора B.
Ответ №1:
Может ли это использование виртуального наследования отдельно от проблемы наследования алмаза вызывать неопределенное поведение или другой вред?
Виртуальное наследование для любых целей наносит этот «вред»:
- Доступ к виртуальному базовому классу осуществляется через указатель, что потенциально медленнее
- Каждый производный класс на всех глубинах должен отвечать за построение виртуальной базы
- Низведение из виртуальной базы должно выполняться через
dynamic_cast
. Быстрееstatic_cast
невозможно.
Ваш пример не вводит никакого неопределенного поведения или вреда, которые не существуют для любого другого использования виртуального наследования.