C++拾遗--this指针

                           C++拾遗--this指针

前言

    在用C++进行面向对象编程时,this指针是一个人尽皆知的东西。但我们真的清楚它吗?下面我们对它的存在意义和使用方法一一进行探讨。

this指针

存在意义:我们为何需要this指针?

看一个简单的例子

#include 
using namespace std;

class MyClass
{
protected:
	int a;
public:
	MyClass(int a) :a(a)
	{}
	void setA(int a)
	{
		this->a = a;
	}
	int getA() const
	{
		return a;
	}
};
int main()
{
	MyClass my1(0);
	MyClass my2(1);
	my1.setA(2);
	my2.setA(3);
	cout << "my1::a = " << my1.getA() << endl;
	cout << "my2::a = " << my2.getA() << endl;
	cin.get();
	return 0;
}
运行



这个例子实在是太简单了!大家用脚指头都能看明白。我们需要深入思考下:

1.setA方法中明明没有this形参,为何在方法体中可以使用this?

答:this形参是隐式定义的,它代表当前对象的内存地址。我们不写,并不代表它不存在。

2.在设计setA方法时,我故意把方法形参(int a)和类成员变量(int MyClass::a)设计成同名的。以至于function body中必须写成 this->a=a;才能完成赋值。若把形参写成不同名的,比如int A,是否可以省略this?

答:可以的。但本质上还是this->a=A;还是那句:我们不写,并不代表它不存在。编译器在进行编译时,会自动把“a=A”改为“this->a=A;”。

3.从以上两个问题还没弄清this的存在意义吗?那就多说一句,程序在内存中的存储原理:代码区是公共的,静态变量是公共的。公共是只有一份的意思。

前者是公共的理由是:节约内存。后者是公共的理由是:逻辑上本该如此!(静态变量的存在意义)

总之,类MyClass的任何对象在调用setA方法时,都是调用同一份代码。但为何会有不同的效果呢?对象my1在调用setA时,是对my1.a进行赋值。对象my2在调用setA时,是对my2.a赋值。它们执行的代码相同,却不会乱掉,就是因为this指针的存在!

这就完了吗?还没有,我们需要进一步指出:this指针隐式定义于方法形参中。那么它的位置是?这不好说,我的推测:就是第一个形参。我的理由:方法调用时,传入的实参是从右向左入栈的,出栈时,第一个位置的参数当然就最先出栈。(若有不同的看法,欢迎讨论!)以下的讨论就暂且基于这种假设。

所以,setA(int a);本质上应该是 setA(MyClass * const this, int a); 

my1.setA(2);本质上应该是 my1.setA(&my1, 2);

再深入,细心的你会发现,我写的是 MyClass * const this,而不是 MyClass * this,多了一个const,为何?这当然也是有理由的!

理由很简单:若this不是const的,则可以随意更改this的指向,如下代码:

void setA(int a)
{
	this = &my;
	this->a = a;
}
当然,这样的代码肯定是通不过编译的。每次对setA的调用都变成了对my.a的赋值。

总结:默认情况下,this的类型是指向类类型非常量版本的常量指针。(《C++Primer》)


还没完,我们还得继续深入……

const成员函数是怎么一回事?它和this有联系吗?

我们知道,const成员函数是不可以对成员变量进行修改的。那它是如何做到的呢?

原因:const对成员函数的修饰,就是对this的修饰。

上面的例子中的int getA()const;本质上是 int getA(MyClass const * const this);


至此,真相终于大白。





本专栏目录

  • C++拾遗 目录

所有内容目录

  • CCPP Blog 目录



    

你可能感兴趣的:(C++拾遗,C++拾遗,c++,this,指针,内存,const)