Каждый экземпляр derive
имеет под-объект базового класса middle1
и под-объект базового класса middle2
.
Если наследование не является виртуальным, то класс подобъект middle1
основы имеет класс субобъект base
базовых, и класс подобъект middle2
Основания также имеет класс субобъект base
базы. Следовательно, каждый экземпляр derive
имеет два поднабора base
, а вызов pd->f()
неоднозначен - какой из объектов base
вы хотите назвать f()
?
Создание наследования виртуальным означает, что middle1
и middle2
будут разделять один объект base
объекта derive
. Это устраняет двусмысленность - есть только один объект base
, который можно вызвать f()
.
Можем ли мы всегда писать публичный виртуальный для безопасности
Не обязательно. Там могут быть иерархии наследования, в которых вы не хотитеmiddle1
и middle2
для общего доступа к объекту base
.Вы могли бы утверждать, что в таких случаях, вы не должны писать класс derive
, который унаследован от обоих, но если вы в конечном итоге с этой ситуацией, то обходной путь будет сделать что-либо:
static_cast<middle1*>(pd)->f();
pd->middle1::f();
указать что вы хотите позвонить f
на middle1
базового класса подъобекта или
static_cast<middle2*>(pd)->f();
pd->middle2::f();
middle2
указать.
виртуальный говорит компилятор, который принимает копию методов и переменных-членов из базы не из middle2 – Prasad