Представьте себе такую ситуацию:
struct Base
{
Base() { }
virtual void call_me();
};
struct A : virtual Base { A() { call_me(); } };
struct B : virtual Base { B() { call_me(); } };
struct Derived : A, B
{
Derived()
: Base() // virtual base is construced in most-derived
, A()
, B()
{ }
};
Теперь предупреждение о том, что промежуточные классы A
и B
могут предположить, что они единственные, которые вызывают Base::call_me()
,Если бы их наследование Base
было не виртуальным, это действительно было бы так, поскольку и A
, и B
имели бы свой собственный уникальный базовый класс.Однако с виртуальным наследованием не до A
и B
, чтобы определить, кто становится их базовым классом, поскольку только конечный класс Derived
устанавливает фактический, единственный базовый класс, которыйявляется общим для всех посредников.Таким образом, в нашем примере и A
, и B
в итоге вызывают call_me()
на одном и том же базовом объекте.
Мораль состоит в том, что операции, которыеза виртуальный базовый класс должен отвечать класс наиболее производный .Поскольку это не жесткая концепция и наследование может быть практически неограниченным, это скользкий путь.Виртуальное множественное наследование - сложная концепция.