我正在瀏覽從某處獲得的代碼,以瞭解vptr和vtable的工作原理。以下是帶輸出的代碼當使用vptr直接調用虛函數時理解輸出
class Base1
{
virtual void fun1() { cout<< "Base1::fun1()" << endl; }
virtual void func1() { cout<< "Base1::func1()" << endl; }
};
class Base2 {
virtual void fun1() { cout<< "Base2::fun1()" << endl; }
virtual void func1() { cout<< "Base2::func1()" << endl; }
};
class Base3 {
virtual void fun1() { cout<< "Base3::fun1()" << endl; }
virtual void func1() { cout<< "Base3::func1()" << endl; }
};
class Derive : public Base1, public Base2, public Base3
{
public:
virtual void Fn()
{
cout<< "Derive::Fn" << endl;
}
virtual void Fnc()
{
cout<< "Derive::Fnc" << endl;
}
};
typedef void(*Fun)(void);
int main()
{
Derive obj;
Fun pFun = NULL;
// calling 1st virtual function of Base1
pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+0);
pFun();
// calling 2nd virtual function of Base1
pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);
pFun();
// calling 1st virtual function of Base2
pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+0);
pFun();
// calling 2nd virtual function of Base2
pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+1);
pFun();
// calling 1st virtual function of Base3
pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+0);
pFun();
// calling 2nd virtual function of Base3
pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+1);
pFun();
// calling 1st virtual function of Derive
pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+2);
pFun();
// calling 2nd virtual function of Derive
pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+3);
pFun();
return 0;
}
OUTPUT:
Base1::fun
Base1::func
Base2::fun
Base2::func
Base3::fun
Base3::func
Derive::Fn
Derive::Fnc
它看起來不錯,但派生類的虛擬函數被調用的方式不被理解。它不應該是這樣的:
// calling 1st virtual function of Derive
pFun = (Fun)*((int*)*(int*)((int*)&obj+3)+0);
pFun();
// calling 2nd virtual function of Derive
pFun = (Fun)*((int*)*(int*)((int*)&obj+3)+1);
這意味着是虛函數的地址,利用其最終指向的派生類的虛函數表的派生類的vptr訪問。
虛擬調用機制是實現定義的。 –
忽視未定義的行爲,這取決於編譯器。閱讀你的編譯器的文檔和/或來源,找出它應該是什麼。 – molbdnilo