(1) 静态
数据成员
①一般地静态数据成员在该类定义之外被初始化,如同一个成员函数被定义在类定义之外一样。在这种定义中的静态成员的名字必须被其类名限定修饰,例如下面是_interestRate的初始化
// 静态类成员的显式初始化
#include "account.h"
double Account::_interestRate = 0.0589;
②静态数据成员的初始化不应该被放在头文件中,而应该放在含有类的非inline 函数定义的文件中。静态数据成员可以被声明为任意类型。例如:
#include <string>
class Account
{
// ...
private:
static const string name;
};
const string Account::name( "Savings Account" );
作为特例,整型的const 静态数据成员可以在类体中用一常量值初始化。例如,如果决定用一个字符数组而不是string 来存储账户的姓名那么我们可以用int 型的const 数据成员指定该数组的长度,例如:
// 头文件
class Account {
// ...
private:
static const int nameSize = 16;
static const char name[nameSize];
};
// 文本文件
const int Account::nameSize; // 必需的成员定义
const char Account::name[nameSize] = "Savings Account";
用常量值作初始化整型的const 静态数据成员是一个常量表达式(constant expression)。如果需要在类体中使用这个被命名的值,那么,类设计者可声明这样的静态数据成员。例如,因为const 静态数据成员nameSize是一个常量表达式,所以类的设计者可以用它来指定数组数据成员name 的长度。在类体内初始化一个const 静态数据成员时,该成员必须仍然要被定义在类定义之外。但是因为这个静态数据成员的初始值是在类体中指定的所以在类定义之外的定义不能指定初始值。
因为name 是一个数组,不是整型,所以它不能在类体内被初始化。任何试图这么做的行为都会导致编译时刻错误,例如:
class Account {
// ...
private:
static const int nameSize = 16; // ok: 整型
static const char name[nameSize] =
"Savings Account"; // 错误
};
name 必须在类定义之外被初始化。
这个例子还说明了一点我们注意到成员nameSize 指定了数组name 的长度,而数组name的定义出现在类定义之外
const char Account::name[nameSize] = "Savings Account";
nameSize 没有被类名Account 限定修饰。尽管nameSize 是私有成员,但是name的定义仍没有错。如同类成员函数的定义可以引用类的私有成员一样,静态数据成员的定义也可以。静态数据成员name的定义是在它的类的域内,当限定修饰名Account::name被看到之后,它就可以引用Account 的私有数据。
③静态数据成员的访问
1. 在类的成员函数中可以直接访问该类的静态数据成员,而不必使用成员访问操作符:
inline double Account::dailyReturn()
{
return( _interestRate / 365 * _amount );
}
2. 在非成员函数中,我们必须以如下两种方式访问静态数据成员:
I. 使用成员访问操作符
class Account {
// ...
private:
friend int compareRevenue( Account& , Account* );
// 余下部分未变
};
// 引用和指针参数来说明对象和指针访问
int compareRevenue( Account &ac1, Account *ac2 )
{
double ret1, ret2;
ret1 = ac1._interestRate * ac1._amount;
ret2 = ac2->_interestRate * ac2->_amount;
// ...
}
ac1._interestRate 和ac2->_interestRate都引用静态成员Account::_interestRate