深度探索C++对象模型(2)——对象(2)——this指针调整

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对象的起始地址

猜你喜欢

转载自blog.csdn.net/qq_34805255/article/details/84483302
今日推荐