有关C++多态的一些测试
由于一直對C++的多態(tài)心存疑慮,今天想徹底弄明明一點,所以做了一些測試,將結(jié)果拿出來同大家一起分享。測試在VC6下進行,以下是測試時用的繼承關(guān)系以及虛函數(shù)的重寫情況(不能貼圖,可惜,可能貼源碼了):
class BaseA
{
public:
???????? BaseA();
???????? ~BaseA();
????????
???????? virtual void printme();
???????? virtual void printme1();
};
class BaseB : public BaseA
{
public:
???????? BaseB();
???????? ~BaseB();
????????
???????? virtual void printme();
};
class BaseC :public BaseA
{
public:
???????? BaseC();
???????? ~BaseC();
???????? virtual void printme();
};
class BaseD:public BaseB,BaseC
{
public:
???????? BaseD();
???????? ~BaseD();
????????
???????? virtual void printme();
???????? virtual void dxx();
};
class BaseF : public BaseD?
{
public:
???????? BaseF();
???????? ~BaseF();
???????? virtual void printme1();
};
?
1、如果繼承體系里沒有C類,即粗線的單重繼承,則以下測試代碼是可行的(先從類實例地址的開始處取得指向vtable的指針,vtable是一個指針數(shù)組,每一個值都指向一個虛函數(shù),因此可以順序遞增去執(zhí)行每一個方法):
void *getp (void* p)
{
?????? return (void*)*(unsigned long*)p;
}
fun getfun (BaseD* obj, unsigned long off)
{
?????? void *vptr = getp(obj);
?????? unsigned char *p = (unsigned char *)vptr;
?????? p += sizeof(void*) * off;
?????? return (fun)getp(p);
}
void testv()
{
?????? BaseF *p = new BaseF;
?????? fun f = getfun(p, 0);
?????? (*f)();
?????? f = getfun(p, 1);
?????? (*f)();
}
輸出為:
is BaseD here
is BaseF here 1
虛函數(shù)表圖如下:
---------圖沒貼上來-------------------
b1
??? BaseD
??????? BaseB
??????????? BaseA
??????????????? _vfptr
??????????????????? [0]???????????? BaseD::printme(void)
??????????????????? [1]???????????? BaseF::printme1(void)
?
其中:BaseF *b1 = new BaseF;
?
此時,如果你想直接調(diào)用A的printme1方法,可用如下方法:
b1->BaseA::printme();
?
2、如果在繼承層次中加入C類,則有了多重繼承,以下將是b1的虛函數(shù)圖:
---------圖沒貼上來-------------------
b1??????????????????????????????????????? 0x02193a10
???? BaseD
???????? BaseB
????????????? BaseA
?????????????????? _vfptr???????????????? 0x004380fc const BaseF::’vftable’{for’baseB’}
?????????????????????? [0]??????????????? 0x00401154 BaseD::printme(void)
?????????????????????? [1]??????????????? 0x004010af BaseF::printme1(void)
???????? BaseC
????????????? BaseA
???? ????????????? _vfptr???????????????? 0x004380f0 const BaseF::’vftable’{for’baseC’}
?????????????????????? [0]??????????????? 0x00401172 [thunk]:BaseD::printme’adjustor{4}’(void)
?????????????????????? [1]??????????????? 0x0040116D[thunk]:BaseF::printme1’adjustor{4}’(void)
?
(此時用上面的代碼手動調(diào)用虛函數(shù)將會出錯,具體內(nèi)存是如何分布的,我沒有去深入研究了)
可以看到,每一個繼承分支都有不同的虛函數(shù)表,此時,如果你想用:
b1->BaseA::printme();
來調(diào)用A的方法,編譯將通不過,告訴你會有歧義。而必須用:
((BaseC *)b1)->BaseA::printme();
來調(diào)用。
總結(jié)
以上是生活随笔為你收集整理的有关C++多态的一些测试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring AOP之ThrowsAdv
- 下一篇: [分享]千万数量级分页存储过程(效果演示