手机版
你好,游客 登录 注册
背景:
阅读新闻

C++拾遗--this指针

[日期:2015-02-19] 来源:Linux社区  作者:zhangxiangdavaid [字体: ]

前言

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

this指针

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

看一个简单的例子

#include <iostream>
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++ Primer Plus 第6版 中文版 清晰有书签PDF+源代码 http://www.linuxidc.com/Linux/2014-05/101227.htm

读C++ Primer 之构造函数陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

读C++ Primer 之智能指针 http://www.linuxidc.com/Linux/2011-08/40177.htm

读C++ Primer 之句柄类 http://www.linuxidc.com/Linux/2011-08/40175.htm

C语言梳理一下,分布在以下10个章节中:

  1. Linux-C成长之路(一):Linux下C编程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成长之路(二):基本数据类型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成长之路(三):基本IO函数操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成长之路(四):运算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成长之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成长之路(六):函数要义 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成长之路(七):数组与指针 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成长之路(八):存储类,动态内存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成长之路(九):复合数据类型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成长之路(十):其他高级议题

本文永久更新链接地址http://www.linuxidc.com/Linux/2015-02/113675.htm

linux
相关资讯       C++  this指针 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款