Что такое виртуальный базовый класс в С++?
О структуре памяти
Кстати, проблема с Dreaded virtual-inheritance Diamond заключается в том, что c++ базовый класс присутствует c++ несколько раз. Таким образом, при virtual-inheritance обычном наследовании вы считаете, что virtual-inheritance имеете:
A
/ \
B C
\ /
D
Но в схеме памяти c++ у вас есть:
A A
| |
B C
\ /
D
Это объясняет, почему virtual-inheritance при вызове D::foo()
возникает проблема cpp неоднозначности. Но реальная проблема c++ возникает, когда вы хотите cpp использовать переменную-член cxx A
. Например, допустим, у нас cxx есть:
class A
{
public :
foo() ;
int m_iValue ;
} ;
Когда вы попытаетесь cpp получить доступ к m_iValue
из D
, компилятор virtual-inheritance будет протестовать, потому virtual-inheritance что в иерархии он увидит cxx два m_iValue
, а не один. И если вы c++ измените один, скажем, B::m_iValue
(то cpp есть A::m_iValue
родитель B
), C::m_iValue
не будет c++ изменен (то есть A::m_iValue
родитель cxx C
).
Здесь пригодится виртуальное c++ наследование, так как с ним virtual-inheritance вы вернетесь к истинному cpp ромбовидному макету, используя cxx не только один метод foo()
, но cxx и один-единственный метод virtual-inheritance m_iValue
.
Что может пойти не так?
Представьте:
A
имеет базовую функцию.B
добавляет в него какой-то прикольный массив данных (например)C
добавляет к нему какую-нибудь интересную функцию, например шаблон наблюдателя (например, наm_iValue
).D
наследуется отB
иC
и, таким образом, отA
.
При нормальном cxx наследовании изменение m_iValue
из cxx D
неоднозначно, и это необходимо cpp разрешить. Даже если это cxx так, внутри D
есть два m_iValues
, так cxx что вам лучше помнить об c++ этом и обновлять их одновременно.
При virtual-inheritance виртуальном наследовании c++ изменение m_iValue
из D
допустимо... Но... Допустим, у c++ вас есть D
. Через его интерфейс c++ C
вы прикрепили наблюдателя. А virtual-inheritance через его интерфейс B
вы обновляете cpp крутой массив, побочным эффектом c++ которого является прямое cpp изменение m_iValue
...
Поскольку изменение virtual-inheritance m_iValue
выполняется напрямую (без cpp использования виртуального cpp метода доступа), наблюдатель, «прослушивающий» через cpp C
, не будет вызываться, поскольку c++ код, реализующий прослушивание, находится virtual-inheritance в C
, а B
не знает об этом...
Заключение
Если cpp у вас есть ромб в вашей иерархии, это virtual-inheritance означает, что вы с вероятностью c++ 95% сделали что-то не так cxx с указанной иерархией.
c++
virtual-inheritance
Что такое виртуальный базовый класс в С++?
Мы используем файлы cookies для улучшения работы сайта. Оставаясь на нашем сайте, вы соглашаетесь с условиями использования файлов cookies. Чтобы ознакомиться с нашими Положениями о конфиденциальности и об использовании файлов cookie, нажмите здесь.