this指针调整 这个事一般存在于多重继承的情况下;
咱们就直接上代码给大家演示:咱们来两个基类和一个派生类;
class A
{
public:
int a;
A()
{
printf("A::A() 的 this指针是:%p!\n", this);
}
void funA() { printf("A::funcA: this = %p\n", this); }
};
class B
{
public:
int b;
B()
{
printf("B::B() 的 this指针是:%p!\n", this);
}
void funB() { printf("B::funcB: 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::funcC: this = %p\n", this); }
};
main中:
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
cout << sizeof(C) << endl;
C myc;
myc.funA();
myc.funB();
myc.funC();
运行起来,看看结果:
a)解释4,4,12尺寸原因。
b)执行C myc;时,我们看到了,父类A的构造函数被调用,this指针是0xXXX,父类B的构造函数被调用,this指针是0xXXXX,子类C同时继承了A类和B类,注意继承顺序,是先继承的A类,后继承的B类,我们注意到子类C的构造函数被执行,this指针是0xXXX,和父类A的this指针相同。
那大家都知道,派生类对象它是包含基类子对象的。如果这个派生类只从一个基类继承的话,那这派生类对象的地址和基类子对象地址是相同。但如果派生类对象同时继承多个基类,那大家就要注意一下,第一个基类子对象的开始地址和 派生类对象开始地址相同,那后续的这些基类子对象的开始地址 和派生类对象的开始地址相差多少呢?那就得到把前边那些基类子对象所占用的内存空间干掉。所以上图,大家注意到了,B类子对象的开始地址是加了4个字节的,因为 A类子对象是占4个字节的;
c)所以,这个图里大家就能观察到一个this指针的调整问题;
当我调用
myc.funA();和myc.funC();
的时候,我的this指针是00CFF844;相同,这是因为基类A子对象和子类C对象的开始地址相同,也就是this指针相同。
当我调用myc.funB();
的时候,因为你这个funB是属于基类B的成员函数,那基类B的this指针就被编译器自动调整成了00CFF848了,与子类C的this指针相差4字节,这4字节正好是基类A子对象的大小吧;
那同理,如果我在C类中覆盖B类的同名函数:
//覆盖父类的同名函数
void funB() { printf("C::funcB: this = %p\n", this); }
我main中:
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
cout << sizeof(C) << endl;
C myc;
myc.funA();
myc.funB();
myc.B::funB();
myc.funC();
看看结果:
总结,你调用哪个子类的成员函数,这个this指针就会被编译器自动调整到对象内存布局中对应该子类对象的起始地址那去;
你听懂了吗?