深度探索C++物件模型(2)——物件(2)——this指標調整
阿新 • • 發佈:2019-01-10
this指標調整
首先看程式碼示例:
#include <iostream> using namespace std; class A { public: int a; A() { printf("A::A()的this指標是:%p!\n",this); } void funA() { printf("A::funA()的this指標是:%p!\n",this); } virtual void fun() { } }; class B { public: int b; B() { printf("B::B()的this指標是:%p!\n", this); } void funB() { printf("B::funB()的this指標是:%p!\n", this); } }; class C: public A,public B //注意繼承順序,決定了後面的記憶體佈局 { public: int c; C() { printf("C::C()的this指標是:%p!\n", this); } void funC() { printf("C::funC()的this指標是:%p!\n", this); } }; int main() { cout << sizeof(A) << endl; cout << sizeof(B) << endl; cout << sizeof(C) << endl; C myc; myc.funA(); myc.funB(); myc.funC(); return 0; }
visual studio2017執行結果:
解釋:
(1)A類物件:非靜態成員變數a佔4個位元組,虛擬函式表指標佔4個位元組,共8個位元組
B類物件:非靜態成員變數b佔4個位元組
C類繼承自A類和B類:它的非靜態成員變數有 int a; int b; int c;,所以12個位元組()
(2)對於子類物件,它是包含父類物件的,會先為其父類物件成員連續分配記憶體空間,而且分配順序按照其繼承順序進行,
如上面的例子中先依次連續分配 父類物件A,B,子類物件C的記憶體空間
(3)對於它的父類物件的this也就指向它本身所在記憶體空間的首地址,而對於子類物件的this它是指向第一個父類物件的首地址,因為整個C物件構成就是它的父類物件+它本身物件,因為(2)中的父類優先連續分配,所以整個子類物件C的首地址也就是父類物件A的記憶體空間的首地址
所以上面的例子中父類物件A和B的this指標都指向它們各自的記憶體空間,而子類物件C的this指標指向A的記憶體空間首地址
圖示理解:
修改程式碼如下:讓C類重寫父類B中的funB()函式
#include <iostream> using namespace std; class A { public: int a; A() { printf("A::A()的this指標是:%p!\n",this); } void funA() { printf("A::funA()的this指標是:%p!\n",this); } virtual void fun() { } }; class B { public: int b; B() { printf("B::B()的this指標是:%p!\n", this); } void funB() { printf("B::funB()的this指標是:%p!\n", this); } }; class C: public A,public B //注意繼承順序,決定了後面的記憶體佈局 { public: int c; C() { printf("C::C()的this指標是:%p!\n", this); } void funC() { printf("C::funC()的this指標是:%p!\n", this); } void funB() { printf("C::funB()的this指標是:%p!\n", this); } }; int main() { cout << sizeof(A) << endl; cout << sizeof(B) << endl; cout << sizeof(C) << endl; C myc; myc.funA(); myc.funB(); myc.B::funB(); myc.funC(); return 0; }
結果:
解釋:
你呼叫哪個子類的成員函式,這個this指標就會被編譯器自動調整到物件記憶體佈局中 對應該子類物件的起始地址那去;
這裡由於在C類中重寫了funB(),所以myc.funB()會呼叫C中的funB,所以此時this指向C物件的起始地址
而在呼叫myc.B::funB()時,呼叫的是B中的funB,所以此時this指向B物件的起始地址