本文共 2754 字,大约阅读时间需要 9 分钟。
struct person{ char _name[20]; char _gender[3]; int _age;};void SetpersonInfo(person* p,char* name, char*gender, int age){ strcpy(p->_name, name); strcpy(p->_gender, gender); p->_age = age;}void Printperson(person* p){ cout << p->_name << "" << p->_gender << "" <_age << endl;}
从上述c语言代码中我们可以看出,函数如果要操纵类对象,必须要将类对象的信息给进来,为了节省空间,传递了该对象的地址。
实际上,在c++类中的成员函数实现方式和上述类似,(非静态)成员函数也有一个隐藏的指针,指向了调用函数的对象本身。这个指针就叫做:this指针。
class person{public: void SetpersonInfo(char* name,char*gender,int age) { strcpy(_name, name); strcpy(_gender, gender); _age = age; } void Printperson() { cout << _name << "" << _gender << "" << _age << endl; }private: char _name[20]; char _gender[3]; int _age;};int main(){ person s1,s2,s3; s1.SetpersonInfo("哈哈", "男", 18); s2.SetpersonInfo("嘿嘿", "女", 19); s3.SetpersonInfo("吼吼", "男", 20); s1.Printperson(); s2.Printperson(); s3.Printperson(); return 0;}
在上述代码中,我们用person类创建了三个对象s1,s2,s3,然后分别调用SetpersonInfo函数来设置每个对象里面的具体信息。
但是我们发现每个对象只用来保存数据信息,代码和数据分开来存储并且只存储了一份,从函数形式来看,SetpersonInfo函数只有一份(如下图所示)并且函数中没有区分不同对象的标志,为什么当s1调用函数时,函数就知道是s1调用而不是其他函数呢?
这就要引入c++中的下一个知识点–this指针。
解答:(非静态)成员函数都有一个隐藏的指针,当调用函数时,该指针自动指向调用函数的对象,该指针存放的就是当前对象的地址,因此,编译器就知道是哪一个对象调用了函数。
this指针:
1.主要作用:
this指针:用来存放当前对象的地址
,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。
this指针是类的一个自动生成、自动隐藏的私有成员,它存在于类的非静态成员函数中,指向被调用函数所在的对象。
全局仅有一个this指针,当一个对象被创建时,this指针就存放指向对象数据的首地址。
2.如何使用:
(1)在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this
(2)当参数与成员变量名相同时使用this指针,如this->n = n (不能写成n = n)
3.this指针特性:
this指针类型:类类型*const
一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果
this作用域是在类的非静态成员函数内部
-this指针是类的非静态成员函数的第一个默认隐含参数,编译器自动维护传递,类编写者不能显式传递
只有在类的非静态成员函数中才能使用this指针,其他函数都不可以
4._thiscall调用约定:
_thiscall只能够用在类的成员函数上
参数从右向左压栈
如果参数确定,this指针通过ecx传递给被调用者;如果参数不确定(_cdecl),this指针在所有参数被压栈之后压入堆栈
对参数个数不定的,调用者清理堆栈,否则函数自己清理堆栈
5.this指针是否可以为空?
class MyClass { public: int i; void hello() { printf("hello\n"); } void print() { printf("%d\n", i); } }; void main() { MyClass* pmy = NULL; pmy->hello(); }
看上面的这段代码,似乎很诡异。 用一个空指针调用成员函数,简直是天大的错误,可以遗憾的是,却是可行的,至少对于上面的这段程序来说,不会照成错误。
为什么?在类初始化的时候,编译器会将它的函数分配到类的外部,当然这也包括静态成员函数,这样的做法,主要是为了节约内存,这也是为什么静态函数可以在对象初始化之前运行的原因。
大家知道,每个对象,都有一个指向自己的this指针,这个指针的值,将会因为对象的不同而不同,它的作用主要就是用来区分不同的对象,这样你就可以根据它来访问不同的对象的成员变量。编译器编译后的成员函数的第一个参数是this指针,通过this指针引用数据成员及调用其它成员函数。
main函数中的hello函数并没有使用类中的任何成员变量,所以,它也就不会用到this指针,此时的this指针是NULL。由于你调用的成员函数没有使用到类的数据成员,所以即使传入的this指针为空,从而我们就可以没有障碍的使用hello函数,然而相对的是,如果你在pmy->hello()之后接着调用pmy->print(),那么将会报空指针错误,因为这个函数试图用this指针访问成员变量i。
结论:
1)NULL对象指针可以调用成员函数2)通过对象调用成员函数,对象的指针会被传入函数中,指针名称为this
3)NULL对象指针调用成员函数时,只要不访问此对象的成员变量,则程序正常运行
4)NULL对象指针调用成员函数时,一旦访问此对象的成员变量,则程序崩溃