类的静态成员

声明静态成员

定义一个类,表示银行账户:

class Account
{
public:
    void calculate() { amount += amount * interestRate }
    static double rate() { return interestRate; }
    static void rate(double);

private:
    std::string owner;
    double amount;
    static double interestRate;
    static double initRate();
}

类的静态成员存在于任何对象之外,对象中不包括任何与静态数据成员有关的数据。

静态成员函数不能声明成 const 的,不能在 static 函数体内使用 this 指针。

使用类的静态成员

作用域运算符直接访问静态成员:

double r;
r = Account::rate(); //使用作用域运算符访问静态成员

使用类的对象、引用或者指针来访问静态成员:

Account ac1;
Account *ac2 = &ac1;
//调用静态成员函数rate的等价形式
r = ac1.rate();  //通过 Account 的对象或引用
r = ac2->rate(); //通过指向 Account 对象的指针

成员函数不能通过作用域运算符就能直接使用静态成员:

class Account
{
public:
    void calculate() { amount += amount * interestRate; }
private:
    static double interestRate;
    //其他成员与之前的版本一致
}

定义静态成员

既可以在类的内部也可以在类的外部定义静态成员函数。

当在类的外部定义静态成员时,不能重复 static 关键字,该关键字只出现在类内部的声明语句:

void Account::rate(double newRate)
{
    interestRate = newRate;
}

必须在类的外部定义和初始化每个静态成员,一个静态数据成员只能定义一次。

静态数据成员定义在任何函数之外,因为一旦被定义就一直存在于程序的整个声明周期中。

定义静态数据成员需要指定对象的类型名,然后类名、作用域以及成员自己的名臣:

//定义并初始化一个静态成员
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; //period是常量表达式
    double daily_tbl[period];
}
  • 如果 period 的唯一用途就是定义 daily_tbl 的维度,则不需要在 Account 外面专门定义 period 。
  • 当需要把 Account::period 传递给一个接受 const int& 的函数时,必须定义 period 。

类的内部提供了一个初始值,则成员的定义不能再指定一个初始值了:

//一个不带初始值的静态成员的定义
constexpr int Account::period; //初始值在类的定义内提供

静态成员能用于某些场景,而普通成员不能

静态数据成员的类型可以是不完全类型,静态数据成员可以就是它所属的类类型。

而非静态数据成只能声明成所属类的指针或引用:

class Bar
{
public:
    //...
private:
    static Bar mem1;//正确:静态成员可以是不完全类型
    Bar *mem2;//正确:指针成员可以是不完全类型
    Bar mem3;//错误:数据成员必须是完全类型
};

可以使用静态成员作为默认实参:

class Screen
{
public:
    //bkground表示一个在类中稍后定义的静态成员
    Screen& clear(char=bkground);
private:
    static const char bkground;
}

非静态数据成员不能作为默认实参,因为它的值本身属于对象的一部分,无法真正提供一个对象以便从中获取成员的值引发错误。

posted @ 2019-10-08 22:29  CodeWithMe  阅读(215)  评论(0)    收藏  举报