7.6类的静态成员
- 声明静态成员 我们通过在成员声明前加上关键字static使得其与类关联在一起,静态成员可以是public或者private的,静态数据成员的类型可以是常量、引用、指针、类类型。
class Account
{
public:
static double rate() {return interestRate; }
static void rate (double);
private:
static double interestRate;
static double initRate();
};
类的静态成员存在任何对象之外,对象中不包含任何与静态成员有关的数据。因此只存在一个interestRate被其他Account对象共享。
静态成员函数也不与任何对象绑定在一起,它们不包含this指针。作为结果,静态成员函数是不能被声明为const的,而且我们也不能在static函数体内使用this指针。这既适用于this的显示使用,也对调用非静态成员的隐式使用有效。
- 使用类的静态成员 使用作用域运算符直接访问静态成员。
double r;
r = Account::rate();
静态成员不属于类的某个对象,但是可以通过使用类的对象、引用或者指针来访问静态成员。
Account ac1;
Account ac2 = &ac1;
r = ac1.rate();
r = ac2->rate();
成员函数不用通过作用域运算符就能直接使用静态成员。
class Account
{
public:
void calculate() { amount += amount * interestRate; }
private:
static double interestRate ;
//其他与之前版本一致
};
- 定义静态成员
既可以在类内也可以在类外定义静态成员函数。在外部定义时,不能重复static关键字,其只能出现在类内声明中。
静态数据成员不属于类的任何一个对象,所以它们不是在创建类时被定义的,不是由构造函数初始化的。一般,不能在类内初始化静态成员,必须在类外部定义和初始化。
double Account::interestRate = initRate();//interestRate的定义也可以访问类的私有成员
- 静态成员的类内初始化
一般,类的静态成员不在类内进行初始化。然而,可以用const整数类型为静态成员提供初始值,不过静态成员必须是constexpr类型的。初始值必须是常量表达式。
class Account
{
public:
static double rate() { return interestRate; }
static void rate(double);
private:
static constexpr int period = 30;
double daily_tbl[period];
};
如果静态成员应用场景仅在编译器可以直接替换它的值的情况下,则一个初始化的const和constexpr不需要分别定义。相反,则必须要有一条定于语句。如果在类内定义了一个初始值,则成员的定义不能在指定一个初始值了。即使一个常量静态数据成员在类内部被初始化了,也应该在类的外部定义一下该成员。
- 特有的适用场景
静态成员独立于任何类的对象。
class Bar
{
public:
//...
private:
static Bar mem1;//正确:静态成员可以是不完全类型
Bar *men2;//正确:指针可以是不完全类型
Bar men3;//错误:数据成员必须是完全类型
};
静态成员可以做默认实参。非静态成员不能做默认实参,因为它的值属于对象的一部分,无法真正提供一个对象以便获取成员的值,引发错误。
class Screen
{
public:
Screen& clear(char = background);
private:
static const char background;
};