有些属性或行为,从逻辑上讲,不属于任何一个具体的对象,而是属于整个类本身。故而本篇就讲解这样的成员,也就是静态成员。

this指针

要理解静态成员,必须先透彻理解普通成员函数是如何工作的。其核心是一个隐藏的参数:this指针。

概念:this指针,它是编译器自动添加到每个非静态成员函数参数列表中的一个常量指针,指向调用该函数的当前对象。

在函数内部,所有对类数据成员的访问,都隐式地通过this指针进行。例如 real = r; 等价于 this->real = r;

一份代码如何操作多个对象?

  • 内存模型:当创建多个对象(如 c1, c2, c3)时,每个对象在内存中拥有自己独立的数据副本(如 re, im)。但是同一个类的所有成员函数,在内存中只有一份代码。
  • 关键矛盾:一份函数代码,如何操作不同对象的数据?
  • 解决方案:调用函数时,将调用者对象的地址作为隐藏参数(this指针)传递给函数。函数体内部的代码 return re;,在编译时会被解释为 return this->re;
  • 调用过程还原:
1
2
c1.real() → 编译器生成调用 complex::real(&c1)。函数内的 this 指向 c1。
c2.real() → 编译器生成调用 complex::real(&c2)。函数内的 this 指向 c2。

静态数据成员

在普通成员的数据模型之上,我们引入 static 关键字。

核心概念:静态数据成员 (Static Data Member)

  • 在类的声明中,使用 static 关键字修饰的数据成员。

  • 根本区别:它不属于类的任何一个对象。它在程序的数据区(全局/静态存储区)拥有唯一的、共享的副本。

  • 生命周期:在程序开始时创建,程序结束时销毁。其生命周期与任何对象无关。

类内声明,在类内部进行声明,仅表明其存在和类型。

1
2
3
4
5
6
class BankAccount {
private:
// 声明静态数据成员
static double interestRate; // 所有账户共享的利率
// ... 其他普通成员
};

类外定义(必须!)

必须在类的外部(通常是在源文件.cpp中)进行一次且仅一次的定义,以分配存储空间。

1
2
// 在某个.cpp文件中
double BankAccount::interestRate = 0.03; // 定义并初始化

image

image