我们先来看一段代码:
1 #include2 3 using namespace std; 4 class A 5 { 6 public: 7 int a; 8 A( ) 9 { 10 printf("A:A()的this指针是%p\n", this); 11 } 12 13 void funcA( ) 14 { 15 printf("A:funcA()的this指针是%p\n", this); 16 } 17 }; 18 19 class B 20 { 21 public: 22 int b; 23 B( ) 24 { 25 printf("B:B()的this指针是%p\n", this); 26 } 27 28 void funcB( ) 29 { 30 printf("B:funcB()的this指针是%p\n", this); 31 } 32 }; 33 34 class C :public A, public B 35 { 36 public: 37 int c; 38 C( ) 39 { 40 printf("C:C()的this指针是%p\n", this); 41 } 42 void funcC() 43 { 44 printf("C:funcC()的this指针是%p\n", this); 45 } 46 }; 47 48 int main() 49 { 50 cout << sizeof(A) << endl; 51 cout << sizeof(B) << endl; 52 cout << sizeof(C) << endl; 53 54 C cobj; 55 56 cobj.funcA(); 57 cobj.funcB(); 58 cobj.funcC(); 59 return 0; 60 }
第一个基类子对象A的起始地址是与派生类对象C是重合的。我们来看一张图片:
上图演示了this指针是如何调整的。在派生类的对象中,基类是作为派生类的子对象存在的,称为基类子对象,当派生类只继承于一个基类时,基类子对象的起始地址是与派生类对象相同的,而当派生类同时继承于多个基类时(多重继承,这里暂时不考虑虚拟继承)
第一个基类子对象的起始地址是与派生类对象重合的,而后续基类子对象的起始地址与派生类对象依次相差前面的基类子对象的长度,比如,D同时派生于A、B、C。D对象的起始地址是0,那么A子对象的起始地址也是0,B子对象的起始地址是0+sizeof(A),而C对象的起始地址为0 + sizeof(A) + sizeof(B)。上面的例子C类派生于A,B。C类对象的地址是006FFD4C,那么A子对象的起始地址和C类对象的起始地址是一样的为006FFD4C,B类对象的起始地址为006FFD4C + sizeof(A) = 006FFD4C + 4 = 006FFD50
如果我们把程修改成如下,输入结果会怎么样呢?
1 #include2 3 using namespace std; 4 class A 5 { 6 public: 7 int a; 8 A( ) 9 { 10 printf("A:A()的this指针是%p\n", this); 11 } 12 13 void funcA( ) 14 { 15 printf("A:funcA()的this指针是%p\n", this); 16 } 17 }; 18 19 class B 20 { 21 public: 22 int b; 23 B( ) 24 { 25 printf("B:B()的this指针是%p\n", this); 26 } 27 28 void funcB( ) 29 { 30 printf("B:funcB()的this指针是%p\n", this); 31 } 32 }; 33 34 class C :public A, public B 35 { 36 public: 37 int c; 38 C( ) 39 { 40 printf("C:C()的this指针是%p\n", this); 41 } 42 void funcC() 43 { 44 printf("C:funcC()的this指针是%p\n", this); 45 } 46 void funcB() 47 { 48 printf("C:funcB()的this指针是%p\n", this); //新增加的代码 49 } 50 }; 51 52 int main() 53 { 54 cout << sizeof(A) << endl; 55 cout << sizeof(B) << endl; 56 cout << sizeof(C) << endl; 57 58 C cobj; 59 60 cobj.funcA(); 61 cobj.funcB(); 62 cobj.funcC(); 63 return 0; 64 }
可以看到,此时三个值都相同了,C类override基类子对象B的funcB函数,此时funB()中的this指针指向C对象的起始地址。