背景:

  c++是在c语言的基础上发展而来的,第一个c++的编译器实际上是将c++程序翻译成c语言程序,然后再用c语言编译器进行编译。c语言没有类的概念,只有结构,函数都是全局函数,没有成员函数。翻译时,将class翻译成struct、对象翻译成结构变量是显而易见的,但是对类的成员函数应该如何翻译?对“my.modify();”这样通过一个对象调用成员函数的语句,又该如何翻译呢?

c语言只有全局函数,因此成员函数只能被翻译成全局函数;“my.modify();”这样的语句也只能翻译成普通的调用全局函数的语句。那如何让翻译后的modify全局函数还能作用在my这个结构变量上呢?答案是引入“this指针”。

示例:

下面来看一段c++程序到c程序的翻译。

c++程序:

class CCar{
public:
int price;
void SetPrice(int p);
}; void CCar::SetPrice(int p){
price=p;
} int main(){
CCar car;
car.SetPrice(20000);
}

翻译后的c程序:

struct CCar{
int price;
}; void SetPrice(CCar* this,int p){
this->price=p;
} int main(){
struct CCar car;
SetPrice(&car,20000);
}  

可以看出,类被翻译成结构体,对象被编译成结构变量,成员函数被翻译成全局函数。但是c程序的全局函数SetPrice比c++的成员函数SetPrice多了一个参数,就是“CCar*this”。“car.SetPrice(20000);”被翻译成“SetPrice(&car,20000);”,后者在执行时,this形参指向的正是car这个变量,因而达到了SetPrice函数作用在car变量上的效果。

this指针的作用:

  实际上,现在的c++编译器从本质上来说也是按上面的方法来处理成员函数和对成员函数的调用的,即非静态成员函数实际上的形参个数比程序员写的多一个。多出来的参数就是所谓的“this指针”。这个”this指针“指向了成员函数作用的对象,在成员函数执行的过程中,正是通过“this指针”才能找到对象所在的地址,因而也就能找到对象的所有非静态成员变量的地址。

示例:

#incldue<iostream>
using namespace std;
class A{
int i;
public:
void Hello(){cout<<"hello"<<endl;}
}; int main(){
A*p=NULL:
p->Hello();
}

  程序的输出结果是:

hello

在上面的程序中,p明明是一个空指针,但它还是能正确调用A的成员函数Hello,因为,参考上面c++到c程序的白泥臆,“p->Hello()”实质上应该是“Hello(p)”,在翻译后的Hello函数中,cout语句没有用到this指针,因此依然可以输出结果。如果Hello函数中有对成员变量的访问,则程序就会出错。

this指针的使用:

c++规定,在非静态成员函数内部可以直接使用this关键字,this就代表指向该函数所作用的对象的指针。

示例:

#include<iostream>
using namespace std;
class A{ public:
double real,imga;
A(double r,double i):real(r),imga(i){}
A addone(){
this->real++;
return *this;
}
}; int main(){
A c1(1,1),c2(0,0);
c2=c1.addone();
cout<<c2.real<<","<<c2.imga<<endl;
}

输出为 2,1

第9行,this指针的类型是A*。因为this指针就指向函数所作用的对象,所以this->real和real是完全等价的。“*this”代表函数所作用的对象,因此执行第16行,进入addone函数后,“*this”实际上就是c1。因此c2的值会变得和c1相同。

注意:

因为静态成员函数并不作用于某个对象,所以在其内部不能使用this指针。

新标准c++程序设计

转发请注明出处

this指针------新标准c++程序设计的更多相关文章

  1. 指针和动态分配内存 (不定长度数组)------新标准c++程序设计

    背景: 数组的长度是定义好的,在整个程序中固定不变.c++不允许定义元素个数不确定的数组.例如: int n; int a[n]; //这种定义是不允许的 但是在实际编程中,往往会出现要处理的数据数量 ...

  2. 正确处理类的复合关系------新标准c++程序设计

    假设要编写一个小区养狗管理程序,该程序需要一个“主人”类,还需要一个“狗”类.狗是有主人的,主人也有狗.假定狗只有一个主人,但一个主人可以有最多10条狗.该如何处理“主人”类和“狗”类的关系呢?下面是 ...

  3. 在成员函数中调用虚函数(关于多态的注意事项)------新标准c++程序设计

    类的成员函数之间可以互相调用.在成员函数(静态成员函数.构造函数和析构函数除外)中调用其他虚成员函数的语句是多态的.例如: #include<iostream> using namespa ...

  4. 多态实现的原理------新标准c++程序设计

    “多态”的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定.例子: #include<iostream> using namespac ...

  5. 类的互相包含------新标准c++程序设计

    #include<iostream> using namespace std; class A; class B{ public: void f(A* pt){}; } class A{ ...

  6. 多态的作用-游戏编程展示------新标准c++程序设计

    游戏软件的开发最能体现面向对象设计方法的优势.游戏中的人物.道具.建筑物.场景等都是很直观的对象,游戏运行的过程就是这些对象相互作用的过程.每个对象都有自己的属性和方法,不同对象也可能有共同的属性和方 ...

  7. 类与类之间的两种关系------新标准c++程序设计

    在c++中,类和类之间有两种基本关系:复合关系和继承关系. 复合关系也称为“has a”关系或“有”的关系,表现为封闭类,即一个类以另一个类的对象作为成员变量. 继承关系也称为“is a”关系或“是” ...

  8. 复制构造函数被调用的三种情况------新标准c++程序设计

    1.当用一个对象去初始化同类的另一个对象时,会引发复制构造函数被调用.例如,下面的两条语句都会引发复制构造函数的调用,用以初始化c2. C c2 (c1); C c2=c1; 这两条语句是等价的.注意 ...

  9. 析构函数的调用------新标准c++程序设计

    示例1: #include<iostream> using namespace std; class CDemo{ public: ~CDemo(){cout<<"d ...

随机推荐

  1. 1050 String Subtraction

    题意:给出两个字符串s1和s2,在s1中删去s2中含有的字符. 思路:注意,因为读入的字符串可能有空格,因此用C++的getline(cin,str).PAT系统迁移之后C语言中的gets()函数被禁 ...

  2. Pycharm快速复制当前行到下一行Ctrl+D

    Pycharm快速复制当前行到下一行Ctrl+D

  3. Rest之路 - Rest架构中的重要概念(二)

    状态无关性 Rest 架构中不维持client,resource and request 的状态,我们通常称 Rest 服务是状态无关的.基于此的优势是为设计Rest架构提供了简便:每一个请求可以被完 ...

  4. 决策树 ID3 C4.5 CART(未完)

    1.决策树 :监督学习 决策树是一种依托决策而建立起来的一种树. 在机器学习中,决策树是一种预测模型,代表的是一种对象属性与对象值之间的一种映射关系,每一个节点代表某个对象,树中的每一个分叉路径代表某 ...

  5. Python——Dict

    Python字典(Dictionary) 字典是一种可变容器模型,可存储任意类型对象. 字典的每个键值(key => value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花 ...

  6. [原创]Java项目统一UTC时间方案

    Java项目统一UTC时间方案 作者:Gods_巨蚁 引言 近期团队的个别项目在进行框架升级后,部分时间值存在8小时误差,原因是错误的将数据库中的时间数据理解成了UTC时间(旧版本认为是北京时间) 考 ...

  7. ffmpeg-URL(转)

    ffmpeg中为方便对资源进行访问,定义了两个结构体,URLContext中是对具体资源文件进行操作的上下文,URLProtocol则是在将资源进行分类的基础上,对某一类资源操作的函数集,熟悉Linu ...

  8. idea写中文到mysql乱码

    idea中中文写入到mysql乱码 参考如下链接: https://segmentfault.com/q/1010000006174975/a-1020000006184639

  9. MySQL与SQLServer的update left join语法区别

    需求: 表A 字段 A_ID, A_NAME, B_ID 表B 字段 B_ID, B_NAME 需求把A的所有A_NAME更新为相应的B的 B_NAME. mysql做法: UPDATE A LEFT ...

  10. java基础知识(一)之数据类型和运算符

    1.标识符:JAVA里面我们可以为之命名的就是标识符,如变量.方法.类等. 但是标识符只能包含字母.数字.下划线(_)和美元符号($),并且只能以字母.下划线和美元符号开头不能以数字开头.2.变量:在 ...