多继承的指针转化跟数据在内存的布局有极大的关系。目前,用msvc11和gcc4.8.3去测试指针转化之后的结果。发现只要不涉及编译增加虚表指针的情况下,派生类的地址多数是和继承列表的首个父类地址相同。当然会有其他问题影响到布局的指针转化。此次要提的内容是,别使用c_style指针转化。正确的指针转化来自于:dynamic_cast/static_cast。
编译器内部生成的指针对象有某个反射机制,能从父类指针正确的映射出派生类地址。无论是普通继承还是virtual继承。具体的内存布局我还要看完书才行,待续。
编译器的实现真是太有学问啦,同时也影响着我们使用这门语言。为了未来几十年能在游戏引擎有所作为,必须吃透C++/C、数学和计算机图形学应用方向等。
#include <cstdio> #include <iostream> #include <string> #include <cstdarg> class A { public: A() { i = 10; }; ~A(){}; virtual void display() { } int i; }; class B { public: virtual void display() { } int j; }; class C :public A,public B { public: int i; int k; private: }; class D:virtual public A { public: int di; virtual void display() override { } private: }; class E :virtual public A { public: int ei; virtual void display() override { } private: }; class F : public D,public E { public: int fi; virtual void display() override { } private: }; int main(int argv, char **argc) { C * pC = new C(); B * pB = dynamic_cast<B*>(pC); A * pA = dynamic_cast<A*>(pC); B * pB_s = static_cast<B*>(pC); A * pA_s = static_cast<A*>(pC); C * pCB_D = dynamic_cast<C*>(pB); C * pCA_D = dynamic_cast<C*>(pA); C * pCB_S = static_cast<C*>(pB); C * pCA_S = static_cast<C*>(pA); pC->i = 100; printf("%d\n",pA->i); printf("pC = %d,pB_d = %d,pA_d = %d,pB_s = %d,pA_s = %d\n", pC, pB, pA, pB_s, pA_s); printf("pCB_D = %d,pCA_D = %d,pCB_S = %d,pCA_S = %d\n", pCB_D, pCA_D, pCB_S, pCA_S); F * pF = new F(); D * pD = dynamic_cast<D*>(pF); E * pE = dynamic_cast<E*>(pF); D * pD_s = static_cast<D*>(pF); E * pE_s = static_cast<E*>(pF); F * pFD_D = dynamic_cast<F*>(pD); F * pFE_D = dynamic_cast<F*>(pE); F * pFD_S = static_cast<F*>(pD); F * pFE_S = static_cast<F*>(pE); printf("pF = %d,pD_d = %d,pE_d = %d,pD_s = %d,pE_s = %d\n", pF, pD, pE, pD_s, pE_s); printf("pFD_D = %d, pFE_D = %d,pFD_S = %d, pFE_S = %d\n", pFD_D, pFE_D, pFD_S, pFE_S); return 0; }
原文地址:http://blog.csdn.net/jingzhewangzi/article/details/41521759