背景:
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++程序设计
转发请注明出处