РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
699 of 815 menu

Виртуальное наследование

Виртуальное наследование - это механизм C++, который применяется при множественном наследовании для того, чтобы избежать дублирования базового класса в иерархии. Если два класса наследуются от одного общего базового класса, а затем от них наследуется ещё один класс, то без виртуального наследования этот общий базовый класс будет присутствовать в конечном классе дважды. Ключевое слово virtual указывается перед именем базового класса в списке наследования и говорит компилятору, что данный базовый класс должен быть представлен в производных классах только в одном экземпляре.

Синтаксис

class Base { }; class Derived1 : virtual public Base { }; class Derived2 : virtual public Base { }; class Final : public Derived1, public Derived2 { };

Ключевое слово virtual может стоять как перед спецификатором доступа, так и после него. Оба варианта равнозначны.

Пример

Рассмотрим классическую проблему ромбовидного наследования без использования virtual:

#include <iostream> using namespace std; class Base { public: int value = 10; }; class Derived1 : public Base { }; class Derived2 : public Base { }; class Final : public Derived1, public Derived2 { public: void print() { // cout << value; // ошибка: неоднозначность } }; int main() { Final obj; cout << obj.Derived1::value << endl; cout << obj.Derived2::value << endl; return 0; }

Результат выполнения кода:

10 10

Здесь value существует в объекте дважды, и обращение obj.value вызовет ошибку неоднозначности.

Пример

Теперь применим виртуальное наследование и посмотрим, как изменится поведение:

#include <iostream> using namespace std; class Base { public: int value = 10; }; class Derived1 : virtual public Base { }; class Derived2 : virtual public Base { }; class Final : public Derived1, public Derived2 { public: void print() { cout << value << endl; } }; int main() { Final obj; obj.print(); obj.value = 20; obj.print(); return 0; }

Результат выполнения кода:

10 20

Теперь value существует в единственном экземпляре, и обращение к нему однозначно.

Пример

Виртуальное наследование также влияет на порядок вызова конструкторов. Рассмотрим пример:

#include <iostream> using namespace std; class Base { public: Base() { cout << "Base" << endl; } }; class Derived1 : virtual public Base { public: Derived1() { cout << "Derived1" << endl; } }; class Derived2 : virtual public Base { public: Derived2() { cout << "Derived2" << endl; } }; class Final : public Derived1, public Derived2 { public: Final() { cout << "Final" << endl; } }; int main() { Final obj; return 0; }

Результат выполнения кода:

"Base" "Derived1" "Derived2" "Final"

Конструктор виртуального базового класса вызывается один раз и до конструкторов промежуточных классов.

Смотрите также

Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить