c++中的this指针和c#中的this引用
先总结一下:
在c++中this为指针,使用"->"操作符来获取当前实例中的成员
在c#中this为引用,使用"."操作符来获取当前实例中的成员
下面内容转载自https://www.xzbu.com/8/view-8757098.htm,特别鸣谢。2019-01-0813:40:33
1 引言
this关键字在C++和C#程序中既随处可见,又无处不在:“随处可见”表明在程序中常常会看到它;“无处不在”说的是在每个类代码中都隐含有它。可以毫不夸张的说,没有理解“this”就没有完全理解类,因为你的类中或隐或现总会有若干个this。“this”到底是什么?它在程序中有什么作用?如何正确地使用它?搞清这些问题对于理解类的基本概念,提高面向对象程序设计的编程技巧大有裨益。
2 什么是this
常常会将“this”简单地理解为“这个”或“我自己”,大致相当于VB中的“Me”。这样理解过于笼统,应进一步明确为“我这个实例(或称当前实例)”,而不是“我这个类”或“我这个数据”等。
C++把this称为this指针,它代表了当前实例的内存地址,通过它可以访问当前实例的数据成员,通常写成“this->成员”或“*this. 成员”的形式。
C#把数据分为值类型和引用类型两大类,类实例属于引用类型,它在栈上存储实例的引用,在堆上存储实例的实际数据,因而把this称为this引用。访问当前实例的成员时,使用“.”操作符,在程序中应写成“this.成员”的形式。
3 c++中的this指针
C++用this指针来代表当前实例的内存地址,有了这个地址,就可以方便地访问到当前实例的所有成员。C++约定可以隐含或显式使用this。
3.1 隐含的this指针
学习过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;
coutxdisplay(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 c#中的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#不支持全局变量的使用,因而类之间信息的交换采用了将类的当前实例的引用传送到另一个类中的手段 来实现。这段程序具有普遍的意义。
c++中的this指针和c#中的this引用的更多相关文章
- f-stack中ipc传递指针从应用中读取信息时挂掉
f-stack中ipc传递指针从应用中读取信息时挂掉 如:创建bridge0./ifconfig bridge0 create./ifconfig f-stack-0 down./ifconfig f ...
- 利用C语言中的函数指针实现c++中的虚函数
C语言中的函数指针 #include<stdio.h> int fun1(int a) { return a*a; } int fun2(int a) { return a*a*a; } ...
- JS中的this指针
1.JS中this指针指向 JS中函数的 this 并不遵守词法作用域规则(即作用域由声明时所处的位置决定),而是取决于函数的调用方式 影响 this 指针的因素有以下: 方法是否由某个对象调用,比如 ...
- QT中使用函数指针
想仿命令行,所以定义了一个类,让一个String 对应一个 function,将两者输入list容器. 类中定义了 QString commandStr; void (MainWindow::*com ...
- Delphi中的函数指针判断是否为空
delphi函数指针 只有@@p才代表了函数指针本身的地址 assigned(p) 判断是否为空 或者用 @p=nil 来判断函数指针是不是为空 Delphi中的函数指针实际上就是指针,只是在使用 ...
- js中的this指针(三)
当一个函数并非一个对象的忏悔时,它会被当作一个函数来调用. 此时,函数中的 this 指针被绑定到了全局对象. 后果:方法不能利用内部函数来帮助工作,由于 this 被绑定了错误的值,将无法共享该方法 ...
- 由javascript中的this指针所想到的
初次结识 this 指针,是在学 <<C++ Primer Plus>>这本书的时候(这本书勉强读了一二遍,之后转学 html+css+js了,不过这是后话). 依稀记得书中举 ...
- c++中基类与派生类中隐含的this指针的分析
先不要看结果,看一下你是否真正了解了this指针? #include<iostream> using namespace std; class Parent{ public: int x; ...
- [BS-21] 关于OC中对象与指针的思考
关于OC中对象与指针的思考 1. 创建对象: OC中可通过代码Person *p = [[Person alloc] init];创建了一个对象p.该过程中内存情况为: 在当前线程的栈(默认1M)中, ...
随机推荐
- JScrollPane的使用
概述 jScrollPane.js是一个轻量级的滑块插件, 非常方便使用. 在前端工业界(写页面)使用非常广泛, 下面我记录下用法, 供以后开发时参考, 相信对其他人也有用. PS: 想起之前我用im ...
- MySQL:字符串字段加索引
1. 使用方式 1.1 全字段加索引 给整个字段加索引,索引存储整个字段的值. 数据量较小时,查询成本高,准确度高: 数据量较大时,比较耗费空间: 1.2 前缀索引 MySQL支持前缀索引,可以定义字 ...
- linux下tar.bz2文件的 解压缩方法
一 使用bzip2解压缩命令进行解压缩: bzip2 -d gcc-4.1.0.tar.bz2 二 上面解压完之后执行下面的命令. tar -xvf gcc-4.1.0.tar 或 tar -xvf ...
- 《JavaScript高级教程》学习笔记一、变量和数据类型
JavaScript的核心语言特性在ECMA-262中是以名为ECMAScript的伪语言的形式来定义的. 一.变量和数据类型 1. 变量 JavaSript是弱类型语言,可以通过var定义任何类型变 ...
- 课程三(Structuring Machine Learning Projects),第二周(ML strategy(2)) —— 0.Learning Goals
Learning Goals Understand what multi-task learning and transfer learning are Recognize bias, varianc ...
- Spring Cloud的注册中心和服务者,消费者的构建
Spring Cloud的注册中心和服务者,消费者的构建 注册中心Eureka: 新建项目stu-eureka: StuEurekaApplication: package com.demo.stue ...
- 归并排序——Merge Sort
基本思想:参考 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法的一个非常典型的应用.首先考虑下如何将2个有序数列合并.这个非常简单,只要从比较2个数列的第一个数,谁小就先取谁,取了 ...
- RPC的基础:调研EOS插件http_plugin
区块链的应用是基于http服务,这种能力在EOS中是依靠http_plugin插件赋予的. 关键字:通讯模式,add_api,http server,https server,unix server, ...
- Android privilege escalation to mediaserver from zero permissions (CVE-2014-7920 + CVE-2014-7921)
墙外通道:http://bits-please.blogspot.com/2016/01/android-privilege-escalation-to.html In this blog post ...
- Android FileObserver 实现原理(inotify)
目录 0x0前言 0x01 FileObserver 使用实例 0x02 FileObserver 实现原理 0x04 完整Demo下载地址 0x0前言 之前在分析某个Android平台加固壳子的时候 ...