Each instance of derive
has a middle1
base class sub-object and a middle2
base class sub-object.
If the inheritance is non-virtual, then the middle1
base class sub-object has a base
base class subobject, and the middle2
base class sub-object also has a base
base class sub-object. Hence, each instance of derive
has two base
sub-objects, and the call pd->f()
is ambiguous -- which of the base
objects do you want to call f()
on?
Making the inheritance virtual means that middle1
and middle2
will share a single base
sub-object of derive
. This removes the ambiguity -- there is only one base
object that f()
could be called on.
Can we always write public virtual for safety
Not necessarily. There may be inheritance hierarchies in which you don't want middle1
and middle2
to share a public base
sub-object. You could probably argue that in such cases, you shouldn't be writing a class derive
that inherits from both, but if you do end up with that situation then the workaround would be to do either:
static_cast<middle1*>(pd)->f();
pd->middle1::f();
to specify that you want to call f
on the middle1
base class sub-object, or
static_cast<middle2*>(pd)->f();
pd->middle2::f();
to specify middle2
.