C++虛擬函式物件模型剖析
阿新 • • 發佈:2019-02-11
測試環境:VS2013
C++中的類物件模型有簡單的,也有複雜的。今天嘗試著剖析一下,以加深對繼承,虛擬函式等的理解。
從最簡單的繼承開始
class Base { public: int b; }; class Derive : public Base { public: int d; }; int main() { cout << sizeof(Derive) << endl; Derive d1; d1.b = 0x01; d1.d = 0x02; return 0; }
定義一個基類Base類,將其成員變數設為公有,為了方便修改。定義一個派生類Derive類,繼承自Base類。在main中輸出派生類的大小,建立一個Derive類物件,對它的成員資料分別賦值以方便在記憶體中進行區分。執行程式輸出8 個位元組,我們可以依據這個數值通過&d1將記憶體中的d1截取出來:
可以看出d1的物件模型:
這個就作為練手。剩下的說的就不那麼詳細了。
繼承+虛擬函式
輸出12:class Base { public: virtual void fun1(){} virtual void fun2(){} public: int b; }; class Derive : public Base { public: virtual void fun1(){} virtual void fun2(){} virtual void fun3(){} public: int d; }; int main() { cout << sizeof(Derive) << endl; Derive d1; d1.b = 0x01; d1.d = 0x02; return 0; }
虛擬函式+多重繼承
class Base { public: virtual void fun1() { cout << "Base::fun1()" << endl; } virtual void fun2() { cout << "Base::fun2()" << endl; } public: int b; }; class C : public Base { public: virtual void fun1() { cout << "C::fun1()" << endl; } public: int c; }; class Derive : public C { public: virtual void fun2() { cout << "Derive::fun2()" << endl; } virtual void fun3() { cout << "Derive::fun3()" << endl; } public: int d; }; int main() { cout << sizeof(Derive) << endl; Derive d1; d1.b = 0x01; d1.c = 0x0c; d1.d = 0x02; d1.fun1(); d1.fun2(); d1.fun3(); return 0; }
輸出16:
菱形繼承+虛擬函式
class Base { public: virtual void fun0() { cout << "Base::fun0()" << endl; } virtual void fun1() { cout << "Base::fun1()" << endl; } virtual void fun2() { cout << "Base::fun2()" << endl; } public: int b; }; class C1 : public Base { public: virtual void fun1() { cout << "C1::fun1()" << endl; } public: int c; }; class C2 : public Base { public: virtual void fun1() { cout << "C2::fun1()" << endl; } public: int c; }; class Derive : public C1, public C2 { public: virtual void fun2() { cout << "Derive::fun2()" << endl; } virtual void fun3() { cout << "Derive::fun3()" << endl; } public: int d; }; int main() { cout << sizeof(Derive) << endl; Derive d1; d1.C1::b = 0x01; d1.C1::c = 0x1c; d1.C2::b = 0x01; d1.C2::c = 0x2c; d1.d = 0x02; d1.C1::fun0(); d1.C1::fun1(); d1.C1::fun2(); d1.C2::fun0(); d1.C2::fun1(); d1.C2::fun2(); d1.fun3(); return 0; }