обычная идиома C ++ :
- публичное виртуальное наследование для интерфейса классов
- частное не виртуальное наследование для реализация классы
В этом случае мы бы имели:
struct interface_base
{
virtual void foo() = 0;
};
struct interface : virtual public interface_base
{
virtual void bar() = 0;
};
struct implementation_base : virtual public interface_base
{
void foo();
};
struct implementation : private implementation_base,
virtual public interface
{
void bar();
};
В implementation
уникальная виртуальная база interface_base
:
- публично наследуется через
interface
: implementation
--public -> interface
--public -> interface_base
- конфиденциально наследуется через
implementation_base
: implementation
--private -> implementation_base
--public -> interface_base
Когда клиентский код выполняет одно из следующих преобразований в базовые:
- преобразование в базовый указатель,
- ссылочная привязка базового типа с производным инициализатора статического типа,
- доступ к унаследованным членам базового класса через lvalue производного статического типа,
важно только то, что существует как минимум один доступный путь наследования от производного класса к данному подобъекту базового класса; другие недоступные пути просто игнорируются. Поскольку наследование базового класса здесь только виртуальное, существует только один субъект базового класса, поэтому эти преобразования никогда не бывают неоднозначными.
Здесь преобразование из implementation
в interface_base
всегда можно выполнить с помощью клиентского кода через interface
; другой недоступный путь не имеет значения вообще. Уникальная interface_base
виртуальная база публично наследуется от implementation
.
Во многих случаях классы реализации (implementation
, implementation_base
) будут скрыты от клиентского кода: будут отображаться только указатели или ссылки на классы интерфейса (interface
, interface_base
).