问题的引入
每个对象中的数据成员都分别占有存储空间,如果对同一个类定义了n个对象,则有n个同样大小的空间以存放n个对象中的数据成员,不同的对象调用同一段目标代码,那么问题来了:当不同对象的成员函数引用数据成员的时候,怎么能保证引用的就是所指定的对象成员呢?
为了能更清晰的表达这个问题,引入如下代码来进行说明:
#include <iostream>
using namespace std;
class Data
{
public:
void SetData(int year, int month, int second)
{
_year = year;
_month = month;
_second = second;
}
void Print()
{
cout << _year << "-" << _month << "-" << _second << endl;
}
private:
int _year;
int _month;
int _second;
};
int main()
{
Data d1;
Data d2;
Data d3;
d1.SetData(2016, 9, 25);
d2.SetData(2016, 8, 26);
d3.SetData(2016, 7, 27);
d1.Print();
d2.Print();
d3.Print();
return 0;
}
在上面的例子中我定义了三个类对象 d1,d2,d3,在main函数中有d1.SetData(2016,9,25),则应该引用对象d1中的三个数据,从而打印出对象d1的日期;有d2.SetData(2016,8,26),则应该引用对象d2中的三个数据,从而打印出对象d1的日期。但是它们都调用的是同一个函数:
void SetData(int year, int month, int second)
{
_year = year;
_month = month;
_second = second;
}
系统怎么知道它分别引用的是d1或d2中的成员呢?
利用C语言中的结构体来进行说明
想弄清楚这个问题,我们利用C语言中的结构体来进行说明,首先先看下面的代码:
struct Date
{
int _year;
int _month;
int _day;
};
void SetDate(Date* _this, int year, int month, int day)
{
_this->_year = year;
_this->_month = month;
_this->_day = day;
}
void PrintDate(Date* _this)
{
printf("%d-%d-%d\n", _this->_year, _this->_month, _this->_day);
}
int main()
{
Date d1;
SetDate(&d1, 2016, 9, 25);
PrintDate(&d1);
return 0;
}
在main函数中定义了一个结构体类型的变量d1,主函数中第二行和第三行程序调用了创建函数和打印函数,但是请注意,SetData函数的参数是四个,而不是三个,其中第一个参数是一个名为_this的指针变量,它指向结构体对象d1,从而我们可以确定是要打印d1中的实参;将这一现象对比到我们刚开始给的那段程序中,就可以明白:
在每一个成员函数中都包含一个特殊的指针,这个指针的名字是固定的,成为this,它是指向本类对象的指针,它的值是当前被调用的成员函数所在的对象的起始地址
例如:当调用成员函数d1.SetData(2016,9,25)时,编译器将对象d1的起始地址赋给this指针,于是在成员函数引用数据成员时,就按照this的指向找到对象a的数据成员。
对this指针做几点说明
1、this指针是隐式引用的,它是作为参数被传递给成员函数的,即在成员函数的形参列表中增加一个this指针。
2、这些都是编译器自己实现的,编程人员不必人为地在形参中加上this指针。
3、”调用对象a的成员函数b“的意思是:在调用成员函数b时,使this指针指向对象a,从而访问对象a中的数据成员。