this指针的调整

时间:2023-12-12 19:36:26

  我们先来看一段代码:

 #include <iostream>

 using namespace std;
class A
{
public:
int a;
A( )
{
printf("A:A()的this指针是%p\n", this);
} void funcA( )
{
printf("A:funcA()的this指针是%p\n", this);
}
}; class B
{
public:
int b;
B( )
{
printf("B:B()的this指针是%p\n", this);
} void funcB( )
{
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 funcC()
{
printf("C:funcC()的this指针是%p\n", this);
}
}; int main()
{
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
cout << sizeof(C) << endl; C cobj; cobj.funcA();
cobj.funcB();
cobj.funcC();
return ;
}

运行结果为:
this指针的调整

第一个基类子对象A的起始地址是与派生类对象C是重合的。我们来看一张图片:

this指针的调整

  上图演示了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

如果我们把程修改成如下,输入结果会怎么样呢?

 #include <iostream>

 using namespace std;
class A
{
public:
int a;
A( )
{
printf("A:A()的this指针是%p\n", this);
} void funcA( )
{
printf("A:funcA()的this指针是%p\n", this);
}
}; class B
{
public:
int b;
B( )
{
printf("B:B()的this指针是%p\n", this);
} void funcB( )
{
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 funcC()
{
printf("C:funcC()的this指针是%p\n", this);
}
void funcB()
{
printf("C:funcB()的this指针是%p\n", this); //新增加的代码
}
}; int main()
{
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
cout << sizeof(C) << endl; C cobj; cobj.funcA();
cobj.funcB();
cobj.funcC();
return ;
}

输出结果为:
this指针的调整

可以看到,此时三个值都相同了,C类override基类子对象B的funcB函数,此时funB()中的this指针指向C对象的起始地址。