多繼承的指針轉化跟數據在內存的佈局有極大的關係。目前,用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;
}