一、this指针
C++中成员变量和成员函数是分开存储的
每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码
那么问题是:这一块代码是如何区分那个对象调用自己的呢?
c++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象
this指针是隐含每一个非静态成员函数内的一种指针
this指针不需要定义,直接使用即可
this指针的用途:
-
当形参和成员变量同名时,可用this指针来区分
-
在类的非静态成员函数中返回对象本身,可使用return *this
#include<iostream> #include<string> #include <fstream> #include<windows.h> using namespace std; class Person { public: Person(int age) { //1、当形参和成员变量同名时,可用this指针来区分 this->age = age;//这里调用的是这个类的成员函数,所以这个指针指向这个类对象 } Person& PersonAddPerson(Person p) { this->age += p.age; //返回对象本身 //比如p2.PersonAddPerson(p1)返回的是p2 return *this; } int age; }; void test01() { Person p1(5); cout << "p1.age = " << p1.age << endl; Person p2(10); //p2.PersonAddPerson(p1)返回的是p2 p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1); cout << "p2.age = " << p2.age << endl; } int main() { test01(); system("pause"); return 0; }
程序运行结果:
二、空指针
空指针:指针变量指向内存中编号为0的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的
C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针
如果用到this指针,需要加以判断保证代码的健壮性
#include<iostream>
#include<string>
#include <fstream>
#include<windows.h>
using namespace std;
//空指针访问成员函数
class Person {
public:
void ShowClassName()
{
cout << "我是Person类!" << endl;
}
void printPerson()
{
if (this == NULL)
{//这个if的作用是防止像test01那样将对象地址置空,然后拿空地址来指向一个值会引起错误
return;
}
//this->mAge = 10;//报错,因为this指向对象,test01里面初始化对象地址为空和test01里面p->mAge = 5;错误一样
cout << mAge << endl;
}
public:
int mAge;
};
void test01()
{
Person* p = NULL;
//p->mAge = 5;//报错,空指针不能访问成员变量
p->ShowClassName(); //空指针,可以调用成员函数
p->printPerson(); //但是如果成员函数中用到了this指针,就不可以了
}
int main()
{
test01();
system("pause");
return 0;
}
this指针存在哪里?
其实编译器在生成程序时加入了获取对象首地址的相关代码。并把获取的首地址存放在了寄存器ECX中(VC++编译器是放在ECX中,其它编译器有可能不同)。也就是成员函数的其它参数正常都是存放在栈中。而this指针参数则是存放在寄存器中。类的静态成员函数因为没有this指针这个参数,所以类的静态成员函数也就无法调用类的非静态成员变量
this指针可以为空吗?
可以为空,当我们调用函数时,如果函数内部不需要使用到this,也就是不需要通过this指向当前对象并对其进行操作时才可以为空(当我们在其中什么都不放或者在里面随便打印一个字符串),如果调用的函数需要指向当前对象,并进行操作,则会发生错误(空指针引用)就跟C中一样不能进行空指针的引用
//
空指针p同时访问了 test() 函数和 change() 函数,在 test() 函数调用过程中没有报错,但是在 change() 函数中报错了。
- 实际上这两个类是这样的:
void test(person *const this) {} void change(person *const this) { cout<< name<< endl; }
根据_thiscall调用约定可知:
(1)_thiscall只能用在类的成员函数上。
(2)参数从左向右压栈。
(3)如果参数个数确定,this指针通过ecx传递给被调函数,如果不参数确定,this指针所在的参数被压栈后压入堆栈。
(4)对于参数不定的,调用者清理堆栈,否则函数自己清理堆栈。
可以看出每次成员函数调用时,this都会被压人。
所以:当把空的this传入 test(NULL)时:
然后 test没有调用任何函数,所以执行函数。当把空的this传入 change(NULL)时:
然后 change通过this指针调用this->name,而this是空的,所以出错了。