一.问题的引出
如下图所示。
用同一个类实例化了两个对象,它们共用同一份成员函数的拷贝。既然是同一份拷贝,那么成员函数又怎么知道是取哪一个对象的成员数据呢?
二.C语言对结构体的访问
这里先回顾一下C语言是怎么在函数中访问结构体成员的。
如下图所示。初始化函数student_init有一个结构体指针参数,需调用者传入,函数内就是通过这个结构体指针确定要初始化的结构体成员的。
三.C++语言对类成员的访问
根据C语言的结构体访问方法,可推测出C++应该有一个隐藏的对象指针指向当前所要访问的对象。这个隐藏的指针就是this指针。
3.1 this指针的概念
当调用一个成员函数时,系统自动产生一个隐藏的指针,这个指针称为this指针,它始终指向产生这个调用的对象,并将该指针作为一个参数自动传递给该成员函数。
3.2 this指针的实现
下面使用Dev-C++开发环境分析this指针是如何实现的。
3.2.1创建C++项目
1.点击“文件”→“新建”→“项目” 。如下图所示。
2.在弹出的对话框中,选择“Console Application”,“C++项目”,输入项目名称。如下图所示。
3.2.2 编写测试代码
测试代码如下。
#include <iostream>
using namespace std;
class CStudent
{
public:
void set_age(int val);
int get_age(void);
private:
char name[50];
int age;
};
void CStudent::set_age(int val)
{
age = val;
}
int CStudent::get_age(void)
{
return age;
}
int main(int argc, char** argv) {
CStudent stu1;
CStudent stu2;
stu1.set_age(10);
stu2.set_age(17);
cout<<"stu1: age "<<stu1.get_age()<<endl;
cout<<"stu2: age "<<stu2.get_age()<<endl;
return 0;
}
3.2.3 选择debug编译
为了进入调试模式,需要选择debug编译,如下图所示。
3.2.4 设置断点
在代码编辑框点击行号即可设置断点。如下图所示。
3.2.5 调试
3.2.5.1 进入调试模式
点击调试选项,再点击调试按钮,此时,程序会自动运行到断点处,并且蓝色高亮显示。如下图所示。
3.2.5.2 添加查看
添加“&stu1”和“&stu2”,查看它们的地址。如下图所示。
添加查看后,可在左侧窗口看到它们的值。如下图所示。
3.2.5.3 查看CPU窗口
点击“查看CPU窗口”按钮,会弹出CPU窗口。如下图所示。
3.2.5.4 单步执行
点击“单步进入”。在CPU窗口中,可看到set_age函数多了一个this参数,如下图所示。
这个this参数的值正好是stu1对象的地址,而我们当前正在由stu1发起调用的成员函数里面。
所以,编译器自动添加了this指针。
3.2.6 结论
1.改变类成员函数的定义,添加隐藏参数this指针。
例如:
void CStudent::set_age(int val)
编译器会将它改为:
void CStudent::set_age(CStudent *const this,int val)
2.对于每个类成员函数的调用,会传入被调用对象的地址。
例如:
stu1.set_age(10);
编译器自动将它改为:
set_age(&stu1,10);