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