C++的this指针和C#的this引用

来源 :电脑知识与技术 | 被引量 : 0次 | 上传用户:xpipi219
下载到本地 , 更方便阅读
声明 : 本文档内容版权归属内容提供方 , 如果您对本文有版权争议 , 可与客服联系进行内容授权或下架
论文部分内容阅读
  摘要:this在C++中称为this指针,它代表了当前实例的内存地址;在C#中称为this引用。使用this可以在类中方便地访问到本类的当前实例,也可以将本类的当前实例方便地传送到另一个类中去。通过多个例子,说明了在C++和C#中显示或隐含使用this的方法,这些方法是编辑中的常用技巧。
  关键词:类;面向对象编程;this;指针;引用
  中图分类号:TP312文献标识码:A 文章编号:1009-3044(2007)04-11052-03
  
  1 引言
  this关键字在C++和C#程序中既随处可见,又无处不在:“随处可见”表明在程序中常常会看到它;“无处不在”说的是在每个类代码中都隐含有它。可以毫不夸张的说,没有理解“this”就没有完全理解类,因为你的类中或隐或现总会有若干个this。“this”到底是什么?它在程序中有什么作用?如何正确地使用它?搞清这些问题对于理解类的基本概念,提高面向对象程序设计的编程技巧大有裨益。
  
  2 什么是this
  常常会将“this”简单地理解为“这个”或“我自己”,大致相当于VB中的“Me”。这样理解过于笼统,应进一步明确为“我这个实例(或称当前实例)”,而不是“我这个类”或“我这个数据”等。
  C++把this称为this指针,它代表了当前实例的内存地址,通过它可以访问当前实例的数据成员,通常写成“this->成员”或“*this. 成员”的形式。
  C#把数据分为值类型和引用类型两大类,类实例属于引用类型,它在栈上存储实例的引用,在堆上存储实例的实际数据,因而把this称为this引用。访问当前实例的成员时,使用“.”操作符,在程序中应写成“this.成员”的形式。
  
  3 this指针
  C++用this指针来代表当前实例的内存地址,有了这个地址,就可以方便地访问到当前实例的所有成员。C++约定可以隐含或显式使用this。
  3.1 隐含的this指针
  来看一个十分简单的C++类:
  学习过C而刚刚接触C++类概念的入门者会对myClass(int m_x)函数中的“x=m_x;”感到十分奇怪:语句中的x是什么?依据面向过程的概念,一个函数中的任何变量都要有出处:要么来自形参,要么是函数内部定义的局部变量,要么是全局变量。此处它们都不是,其实他们就是类的成员变量x。一个类可以创建多个实例,那x是哪个实例的数据呢?x又如何能够穿透函数的屏蔽而在myClass()函数中变得可见呢?答案是:x是当前实例的数据,它们由this指针引导着,在类的成员函数中当然可见。
  C++约定,在类的每个非静态成员函数的参数表中,都隐含有一个形参this,它是一个本类类型的指针变量,其作用是将当前实例的地址传送到函数内部,以便函数知道当前实例的数据往哪里存取。如此,上例的myClass()函数未隐去参数this之前的本来面貌是:
  myClass(myClass * this,int m_x)
  {this->x=m_x; }
  如此一来,这个函数理解起来就不存在任何问题了。
  由于每个非静态成员函数都有这个参数this,为了简化编程,C++对这个参数作了隐含处理,这个函数就变成了
  myClass(int m_x)
  {this->x=m_x; }
  至于函数内部的this->x中的this,可显式使用也可隐含,为了简便,一般都会隐去,于是便成了“x=m_x”。
  了解以下结论至关重要:在类的每个非静态成员函数的参数表中,都隐含有一个形参this,它代表了当前实例的地址,在类的成员函数中使用当前实例的数据成员时,直接写出它们的变量名就行了,其实此时它们前面都有一个隐含的this->。
  知道了这一点,就可以理解类的运算符重载作为成员函数时,为什么可以省去一个形参(例如2个操作数只需1个形参),那是因为第一个参数就是this,而将其隐去了的缘故。
  3.2 显式使用this指针
  既然可以按约定省去this,C++程序员一般不会显式使用this指针。然而有时为了明确变量的归属,或者为了向成员函数内部传入当前实例的地址,或者需要强调使用当前实例,必须显式使用this指针。
  3.2.1 区分不同作用域的变量
  下例C++程序中有三个作用域不同的x:全局变量x、类成员数据x和成员函数的局部变量x。
  此时display()函数输出的是哪个x呢?C++规定,先匹配局部变量x,再匹配类的成员变量x,最后匹配全局变量x。因而输出结果应该是x=3。
  若要输出当前实例的成员数据x,此时就必须显式指明this->x;若要输出全局变量x,需要用域操作符指明::x。为了验证起见,将display()函数改为如下形式(其余代码不变):
  void myClass1::display()
  { int x=3;
  cout<<”全局x=”<<::x<<”,”;
  cout<<”成员x=”<x<<”,”;//此处this强调当前实例
  cout<<”局部x=”<  运行结果为:全局x=1,成员x=2,局部x=3。
  3.2.2 this作函数的实参
  下例中以this指针作函数调用的实参,将当前实例的地址(自身地址)传入函数内。
  //向B类的成员函数传入A类的实例地址
  {p1->display(this);//B类的display调用A类的display函数此处this是将B类当前实例的地址传入到A类的成员此例中关键的语句就是“p1->display(this);”,它是B类的成员函数display的一句,作用是通过A类的指针p1去调用A类的成员函数display,但该函数需要B类实例地址作实参,那当然是它自己,即this。
  3.2.3 用“*this” 代表当前对象
  有时,类的成员函数或运算符需要强调当前对象,就必须用“*this”来表示。例如给上例中的A类增加一个前增运算符,它要求返回当前对象。
  可以看出,以上三例中的this是无可替代的,此时必须显式使用this指针。
  
  4 this引用
  由于C#受管制代码不允许直接对地址进行操作,因而C#采用this引用来访问当前实例的数据。C#的this引用与C++ 的this指针在用法上基本类似,对于隐含的约定也是相同的。C#和C++毕竟是两种不同的语言,由于this引用对类成员的访问采用“.”操作符,其亲和力远胜于“->” 操作符,因而在C#程序中可看到更多的this。经常在程序中看到用this作函数调用的实参,此时往往体现了编程者的匠心。
  下一段C#程序演示了在一个类中去控制另一个类的属性:项目App1中有两个窗体,窗体1(Form1)中有一个命令按钮,单击它时显示窗体2(Form2)。窗体2中也有一个命令按钮,单击它时将窗体1的背景色改为蓝色。为压缩篇幅,将程序中大部分由.NET FrameWork自动生成的代码隐去(不会影响对程序的理解),留下来的代码中有阴影的部分是加上去的。
   Form2.GetForm1(this);//在Form1类中以this作实参调用Form2类的成员函数GetForm1, 就能将Form1类的当前实例传送到Form2类中去。}
  // 这个函数在Form1中调用时是以this作实参(Form2.GetForm1(this))
  // 因而fm1和Form1Ref都是Form1的当前实例的引用
  程序说明了如何在一个类中去获取或操纵另一个类的信息的方法。因为C#不支持全局变量的使用,因而类之间信息的交换采用了将类的当前实例的引用传送到另一个类中的手段来实现。这段程序具有普遍的意义。
  参考文献:
  [1]钱能.C++程序设计教程[M].北京:清华大学出版社,1999.
  [2]张国锋.C++语言及其程序设计教程[M].北京:电子工业出版社,2001.
  [3]美James P.Cohoon,等,刘瑞挺,译.C++程序设计[M].北京:电子工业出版社,2002.
  [4]陈志泊,王春玲.面向对象程序设计____C++[M].北京:人民邮电出版社,2004.
  [5](美)Simon Robinson,等著,康博,译.C#高级编程[M].北京:清华大学出版社,2002.
  [6]黎晓东,李华飚,等.精通C#编程[M].北京 科学出版社,2002.
  [7]田原.C#程序设计[M].北京:交通大学出版社,2005.
  [8]杨宏伟,李晶.C#程序员开发手册[M].北京:希望电子出版社,2005.
  [9]唐耀主.C#程序设计实用教程[M].北京:中国水利水电出版社,2005.
  本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。
其他文献
摘要:本文介绍了遗传算法的基本知识,并利用遗传算法解决TSP(旅行商)问题,在此基础上,用免疫遗传算法进行优化对比。  关键词:遗传算法;TSP旅行商问题;免疫算法  中图分类号:TP311文献标识码:A 文章编号:1009-3044(2007)04-11047-01    1 引言  生物通过许多代的进化才能更好的繁殖,适应了不断改变的外界环境因素而生存。遗传算法利用生物基础,将特定问题转化成生
期刊
摘要:主要介绍了实验用电流表如何运用OpenGL在VC++.NET环境下的设计与实现问题。最后实现了电流表的三维可视化以及通过鼠标实现电流表的缩放和移动功能,还实现了电流表指针随电流而准确及时变化的功能。  关键词:OpenGL;电流表;仿真  中图分类号:TP391文献标识码:A文章编号:1009-3044(2007)04-11043-02    1 引言  物理学是一门实验科学,学生不仅可以从
期刊
摘要:粒子群算法原理简单,易于实现,是进化算法中优化效率很高的算法。针对确定环境下的问题优化,提出采用粒子群算法对其进行优化求解。通过对确定性环境下的Benchmark函数的算法仿真研究,表明粒子群算法在确定性问题优化中具有快速收敛性和精确性的特点。  关键词:粒子群算法;确定性问题;优化  中图文类号:TP301 文献标识码:A文章编号:1009-3044(2007)04-11027-01   
期刊
摘要:将现有MPI并行程序移植到网格环境下有着非常现实的意义,本文介绍了网格计算的概念和MPI并行计算模型,阐述了将现有的MPI并行程序移植到Globus网格环境下的重要性,并针对这类移植的一种折中方案——MPICH-G2进行了研究、实验,总结了这种方案的特点和相关技术。  关键字:网格计算;并行计算;MPI;Globus  中图分类号:TP393文献标识码:A文章编号:1009-3044(200
期刊
摘要:该文以BCH(67,53)为例,提出了一种改进的,适合在FPGA上实现的BCH译码算法,并用Xilinx公司Virtext2pro器件实现了BCH(67,53)码的译码。该算法基于BM迭代,与传统的BCH译码算法相比,具有硬件实现简单,运算速度快,消耗资源少等优势。经仿真验证,对于码组中任意小于等于两比特的随机错误都可以给予纠正,且运行可靠。目前,该BCH译码器已成功地应用在DVB-T(数字
期刊
摘要:Python是一种敏捷开发项目经常采用的语言。本文介绍了在Python敏捷项目中结合类似epydoc文档系统,使在doctest单元测试同时能够产生同步的最新文档,比如常用的功能说明文档等,在敏捷开发中常被称作敏捷文档。  关键词:Python;敏捷开发;敏捷文档;doctest;单元测试;执行文档;epydoc   中图分类号:TP311文献标识码:A文章编号:1009-3044(2007
期刊
摘要:随着电子商务的流行,开始出现了移动商务,在移动中处理商务成为现实。如何高效地实现移动商务,成为一个新的研究课题。本文研究了基于XML和J2ME的无线联机定购系统的实现,并且设计了一个飞机票定购系统。本系统使用J2ME平台的移动信息配置文件(MIDP)和第三方的XML解析器来实现,应用程序分为两个部分:客户端和服务器端。  关键词:J2ME;XML;HTTP;XML解析器  中图分类号:TP3
期刊
摘要:对一个程序用Labview等语言的分别实现的研究,是为了使读者了解许多软件都可以达到相同或相似的结果。通过具体的程序设计,使大家知道软件设计方法的差异性,可以根据自己喜欢的方式,选择语言。  关键词:软件;Labview;Matlab;语言  中图分类号:TP311文献标识码:A文章编号:1009-3044(2007)04-11060-02    1 引言  比较两个无符号数的大小,并求其平
期刊
摘要:分析了MPI环境下算法设计的特点,描述了在MPI环境下实现Mandelbrot集的三种算法,并对它们进行了比较。  关键词:Mandelbrot;并行算法;MPI  中图分类号:TP312文献标识码:A文章编号:1009-3044(2007)04-11055-02    1 Mandelbrot集  Mandelbrot集[1]是复数平面中的点集,当对一个函数迭代计算时,这些点将处于准稳定状
期刊
摘要:介绍了Philips LPC2148微控制器和实时操作系统μC/OS-Ⅱ的特点。以优龙公司的开发板YL-LPC2148为硬件平台,阐述了如何将源代码开放的μC/OS-Ⅱ移植到LPC2148微控制器上,并指出了在移植过程中的重点和难点。  关键词:嵌入式操作系统;实时操作系统;μC/OS-Ⅱ; 移植  中图分类号:TP303 文献标识码:A文章编号:1009-3044(2007)04-1104
期刊