C++程序翻译成C语言程序
C++语言是在C语言的基础上发展过来的,第一个C++的编译器实际上是将C++程序翻译成C原因程序,再通过C语言编译器进行编译。
然而C语言中没有类的概念,只有结构,而且函数还是全局函数,没有类成员函数。在翻译时,将class翻译为struct、对象翻译成结构变量,但是对类的成员函数应该如何翻译,对MyCar.Modify();这样通过一个对象调用成员函数的语句,又该怎么样翻译?
C语言中只有全局函数,因此成员函数被翻译成全局函数:MyCar.Modify()这样的语句也被翻译成普通的调用全局函数的语句。如何让翻译后的Modify全局函数还能够作用在MyCar这个结构变量上?就"引用this"指针。
C++中:
class CCar{
public:
int price;
void SetPrice(int p){
price=p;
}
};
int main(){
CCar car;
car.SetPrice(2000);
return 0;
}
翻译后的C程序:
Struct CCar{
int price;
}
void SetPrice(struct CCar* this,int p){
this->price=p;
}
int main(){
struct CCar car;
SetPrice(&car,2000);
return 0;
}
类被翻译成结构体,对象被翻译成结构变量,成员函数被翻译成全局函数。但是在C语言中的全局函数SetPrice比C++中的成员函数SetPrice多一个参数,就是struct CCar *this 。car.SetPrice(2000); 被翻译成SetPrice(&car,2000),后者在执行时,this 形参指向的正是 car 这个变量,因而达到了 SetPrice 函数作用在 car 变量上的效果。
this指针在这里的作用
现在C编译器从本质上来说也是按上面的方法来处理成员函数和对成员函数的调用,即非静态成员函数实际上的形参个数比程序员写的多一个。多出来的参数就是所谓的“this指针”。这个“this指针”指向了成员函数作用的对象,在成员函数执行过程中,正是通过“this指针”才能找到对象所在地址,因而也就能够找到对象的所有非静态成员变量的地址。
#include <iostream>
using namespace std;
class Student{
int i;
public:
void Hello(){
cout<<"Hello"<<endl;
};
int main(){
A* p=NULL;
p->Hello();
}
在程序中,p本来是一个空指针,为何通过p还能调用A的成员函数Hello?因为,参数C++到C程序的翻译,p->Hello()实质上应该是Hello(p),在翻译后的Hello函数中,cout语句没有用到this指针,因此还可以输出结果。如果Hello函数中有对成员变量的访问,则程序会报错。
C++规定,在非静态成员函数内部可以直接使用this关键字,this关键字就代表指向该函数所作用的对象的指针:
#include<iostream>
using namespace std;
class Complex{
public:
double real,imag;
Complex(double r,double i):real(r),imag(i){}
Complex AddOne(){
this->real++;
return *this;
}
};
int main(){
Complex c1(1,1),c2(2,2);
c2=c1.AddOne();
cout<<c2.real<<","<<c2.imag<<endl;
return 0;
}
this指针的类型是Complex *。因为this指针就指向函数所作用的对象,所以this->rear和real是完全等价的。*this代表函数所作用的对象,进入c2=c1.AddOne()函数后,*this实际上是c1。因此c2值会变得与c1值相同。
因为静态成员函数并不作用于某个对象,所以在其内部不能使用this指针;否则,这个this指针不知道指向何处。
class与struct的区别
从语法上讲,class与struct类型定义有三点区别:
①默认继承权限区别:如果不明确指定,class的继承将会按private继承处理,struct继承会按public继承处理。
②成员默认访问权限:class的成员默认是private权限,struct默认为public权限。
③struct类型名可以同时作为变量名,class不可以。因为class各类型变量定义时直接是类名。而struct是struct+结构体名来定义变量的。
最后,作为语言的两个关键字,除去定义类型时有上述区别之外,另外还有一点点:“class”这个关键字还用于 定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。