类成员函数的存储方式
类大小 sizeof(class)
对于类的大小,发现成员函数并不用类的存储空间。这引发了我们的思考,函数成员 存储在什么地方,数据成员每个对象会有一份,函数成员会不会也是这样呢?
#include <iostream>
using namespace std;
class Time
{
public:
void dis() { cout<<hour<<minute<<sec<<endl; }
private:
int hour;
int minute;
int sec;
};
int main()
{
cout<<sizeof(Time)<<endl;//12
return 0;
}
运行结果为;
我们前面已经验证过:
一个对象所占的空间大小只取决于该对象中数据成员所占的空间,而与成员函数无关。
#include <iostream>
using namespace std;
class Time
{
public:
Time(int h, int m, int s)
:hour(h), minute(m), sec(s)
{}
void dis() { cout<<hour<<minute<<sec<<endl; }
private:
int hour;
int minute;
int sec;
};
int main()
{
cout<<sizeof(Time)<<endl;//12
Time t1(1, 2, 3); t1.dis();
Time t2(4, 5, 6); t2.dis();
Time t3(7, 8, 9); t3.dis();
return 0;
}
运行结果为:
那么类内函数既然不占用对象的大小,那么到底存储在哪里?有又几份?
类成员函数的可能存储方式
用类去定义对象时,系统会为每一个对象分配存储空间。如果一个类包括了数据和函数,要分别为数据和函数的代码分配存储空间。
按理说,如果用同一个类定义了 10 个对象,那么就需要分别为 10 个对象的数据和函数代码分配存储单元。
类成员函数的实际存储方式
能否只用一段空间来存放这个共同的函数代码段,在调用各对象的函数时,都去调用这个公用的函数代码。
显然,这样做会大大节约存储空间。C++编译系统正是这样做的,因此每个对象所占用的存储空间只是该对象的数据部分所占用的存储空间,而不包括函数代码所占用的存储空间
那么这里有个疑问,当对象调用公用函数时,如何确定,访问的成员是调用对象的成员呢?
beacuse of this
所有的对象都调用共用的函数代码段,如何保证访问的是调用对象的成员呢?为此, C++设置了 this 指针,对象在调用公用函数时,并将对象的指针作为隐含参数传入其内,从而保证了访问的成员,属于调用者。
#include <iostream>
using namespace std;
class Time
{
public:
Time(int h, int m, int s)
:hour(h), minute(m), sec(s) {}
void dis() //void dis(Time *p)
{
cout << "this=" << this << endl;
cout << this->hour << ":" << this->minute << ":" << this->sec << endl;
}
private:
int hour;
int minute;
int sec;
};
int main()
{
Time t(1, 2, 3);
Time t2(2, 3, 4);
t.dis(); //等价于 t.dis(&t)
t2.dis();//等价于 t.dis(&t2)
return 0;
}
运行结果为:
this 指针作为隐式参数被传入,这是编译器层面完成的,上例中也可以作为显示参数传入,效果是一样的,每一个类内函数都有一个隐式参数及就是this指针,当然了,显示参数传入,这是完全没必要的。
总结
类的成员函数只有一份,在对象调用过程中,传入对象的地址,具体表现为this。
不论成员函数在类内定义还是在类外定义,成员函数的代码段都用同一种方式存储
应当说明,常说的 “某某对象的成员函数”,是从逻辑的角度而言的,而成员函数的存储方式,是从物理的角度而言的,二者是不矛盾的。类似于二维数组是逻辑概念,而物理存储是线性概念一样。