我们首先先定义一个学生类
class student {
public:
void InitStudent(const char* name, const char* gender, int age) {
strcpy(_name, name);
strcpy(_gender, gender);
_age = age;
}
void PrintStudent() {
cout << _name << " " << _gender << " " << _age << endl;
}
private:
char _name[20];
char _gender[10];
int _age;
};
int main() {
student p1, p2, p3;
p1.InitStudent("zhangsan", "男",20);
p2.InitStudent("lisi", "男",21);
p3.InitStudent("mazi", "女",22);
p1.PrintStudent();
p2.PrintStudent();
p3.PrintStudent();
system("pause");
return 0;
}
我们在上面的主函数中定义了三个对象:p1,p2,p3;然后这三个对象又分别调用了student
类里面的InitStudent这个方法。但是这个InitStudent的方法怎么知道我应该把这个名字复制到p1,p2,还是p3这个对象里面呢?
- C++中通过引入this指针解决这个问题。即:C++编译器给每个“成员函数”增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成
接下来我们调用第一个对象,看this指针在函数体内是怎么区分不同对象的
class student {
public:
void InitStudent(const char* name, const char* gender, int age) {
cout << this << endl;//打印this指针的地址
strcpy(_name, name);
strcpy(_gender, gender);
_age = age;
}
void PrintStudent() {
cout << _name << " " << _gender << " " << _age << endl;
}
private:
char _name[20];
char _gender[10];
int _age;
};
int main() {
student p1, p2, p3;
cout << &p1 << endl;//打印p1这个对象的地址
p1.InitStudent("zhangsan", "男",20);
system("pause");
return 0;
}
我们先来看一下程序打印结果
我们发现this指针地址跟第一个对象的地址是一样的。这就可以说明当我们设置的对象在调用类里面的方法时,C++编译器给每个成员函数增加了一个隐藏的指针参数,让这个指针指向当前对象,接着再用这个函数来设置这个对象。
this指针的特性
- this指针的类型:类类型* const:即this的指向不能修改,一修改就会报错。如下图:
- 只能在成员函数内部使用
我们在主函数内部打印一下this指针的地址看能不能成功
- this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针
- this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递(大部分情况下是通过ecx寄存器传递的,还有少部分是通过压栈的方式来传的)
图中的_thiscall和_cdecl是调用约定。成员函数默认的调用约定是_thiscall。如果调用约定是_thiscall则this指针就是通过ecx寄存器来传递的。如果调用约定是_cdecl,则this指针就是通过压栈的方式来传递的。那么问题来了- this指针到底存放在哪呢?
- 当一个对象调用某成员函数时会隐式传入一个参数,这个参数就是this指针,this指针中存放的就是这个对象的首地址。编译器在生成程序时加入了获取获取对象首地址的相关代码。并把获取的首地址存放在了寄存器ECX中(其他编译器可能有所不同)。也就是成员函数的其他参数正常都是放在栈上,而this指针参数则是存放在寄存器中。
- this指针可以为空吗?
- 可以为空,当我们调用函数的时候没有用到this指向当前对象并对其操作的时候才可以为空,如果调用的函数需要指向当前对象,并进行操作,则会发生错误(空指针引用),就跟C语言一样不能进行空指针的引用。
运行结果:
- 可以为空,当我们调用函数的时候没有用到this指向当前对象并对其操作的时候才可以为空,如果调用的函数需要指向当前对象,并进行操作,则会发生错误(空指针引用),就跟C语言一样不能进行空指针的引用。
- this指针到底存放在哪呢?