Термин «виртуальный класс» на сегодняшний день имеет два совершенно разных определения:
виртуальный класс — это место для онлайн-обучения, куда заходят «ученики» (необязательно школьники!) и получают какую-то обучающую информацию; такой вид классов получил сильное распространение с приходом коронавирусной инфекции и с массовым переходом людей в онлайн-жизнь;
виртуальный класс — это термин, принадлежащий программированию и выражающий специфическое обозначение класса, объект которого будет общим для применения другими дочерними классами.
О первом определении термина «виртуальный класс» мы поговорим в одной из следующих статей, а сегодня разберем, что такое виртуальный класс в программировании.
Виртуальный класс в программировании — что это?
Виртуальный класс — это некий базовый объект в программировании. Он создается только один раз, а потом применяется другими объектами в дереве наследования. Определяется он словом «virtual». Основная цель создания виртуального класса — предотвратить появление нескольких «интерпретаций» такого класса при использовании множественного наследия. Виртуальный класс часто применяется в языке программирования С++.
На практике виртуальный класс решает так называемую «проблему ромба» или «алмазную проблему», которая доставляет много проблем, а ее диаграмма будет выглядеть так:
В такой ситуации, когда вам нужно будет инициировать создание объекта класса «Moto», по умолчанию у вас будет 2 копии класса «PoweredAuto»: одна будет из «Jeep», а другая — из «Vaz». Иногда две копии одного объекта из разных классов будут уместны, но в большинстве случаев потребуется, чтобы «Jeep» и «Vaz» использовали только одну копию «PoweredAuto». Чтобы достичь этого, нужно будет создать «виртуальный класс» при помощи слова «virtual». В нашем случае это будет выглядеть примерно так:
class PoweredAuto
{
};
class Jeep: virtual public PoweredAuto
{
};
class Vaz: virtual public PoweredAuto
{
};
class Moto: public Jeep, public Vaz
{
};
В этом случае, если мы будем создавать объект «Moto», в ответ мы получим только одну копию «PoweredAuto» в объекте «Moto», при этом сама копия будет применяться и «Jeep», и «Vaz».
Однако может возникнуть вопрос: если «Jeep» и «Vaz» применяют общий класс «PoweredAuto», то кто отвечает за создание последнего? В этой ситуации за его создание будет отвечать «Moto», а точнее, конструктор «Moto». Получается, что классу «Moto» можно будет единственный раз вызвать напрямую конструктор, который не является его родительским.
На практике это будет выглядеть так:
#include <iostream>
class PoweredAuto
{
public:
PoweredAuto(int motor)
{
std::cout << "PoweredAuto: " << motor << '\n';
}
};
// хочется отметить, что теперь PoweredAuto будет «виртуальным классом»
class Jeep: virtual public PoweredAuto
{
public:
Jeep(int jeep, int motor)
// эта строчка необходима для создания объектов Jeep,
// но в нашем случае попадает под игнорирование
: PoweredAuto{ motor }
{
std::cout << "Jeep: " << jeep << '\n';
}
};
// нужно отметить, что здесь «PoweredAuto» также будет «виртуальным базовым классом»
class Vaz: virtual public PoweredAuto
{
public:
Vaz(int vaz, intmotor)
// эта строчка необходима для создания объектов Vaz,
// но в нашем случае также попадает под игнорирование
: PoweredAuto{ motor }
{
std::cout << "Vaz: " << vaz << '\n';
}
};
class Moto: public Jeep, public Vaz
{
public:
Moto(int jeep, int vaz, int motor)
: PoweredAuto{ motor }, // PoweredAuto создается здесь
Jeep{ jeep, motor }, Vaz{ vaz, motor }
{
}
};
Как видно, PoweredAuto создается единственный раз.
Нужно отметить несколько моментов по работе с виртуальным классом:
Виртуальный класс всегда создают перед его невиртуальными «братьями».
Посмотрите внимательнее на пример: конструктор «Jeep» и «Vaz» все еще вызывают «PoweredAuto», однако при создании «Moto» эти вызовы попадают под игнорирование, потому что за создание «PoweredAuto» в нашем случае отвечает «Moto», а не «Jeep» или «Vaz».
Даже если «Moto» будет унаследован только от «Jeep», а «Jeep» был унаследован от «PoweredAuto», за создание «PoweredAuto» все равно будет отвечать «Moto».
Заключение
Мы показали самый простейший пример, по каким принципам реализуется виртуальный класс в С++. Однако «виртуальный класс» — это очень объемная тема, которая требует глубокого изучения перед ее применением.

Другое