以下内容主要来自于C++ Primer中文版第四版12.6节。
对于一个已经定义的类,有的时候需要定义这个类的一个全局对象来获取或管理全体类对象的相关信息,比如统计所有类对象的数量。但是全局对象会带来问题:全局对象可被用户随意修改,破坏了封装性。因而常常用类静态成员来代替全局对象。
通常,非static数据成员存在于类类型的每个对象中,而static数据成员独立于该类的任意对象而独立存在;每个static数据成员是与类关联的对象,而不与类对象关联。
类也可以定义static成员函数,static成员函数没有this形参,它可以直接访问类的static成员,但不能直接访问非static成员。
(1)使用static成员的优点
较全局对象,使用static成员有以下几个优点:
a. static成员位于类的作用域中,因而可以避免与其他类的成员或全局对象名字冲突;
b. 可以实施封装 static成员可以是私有成员,而全局对象不可以;
c. static成员通过类操作,从而提高程序的可读性。
(2)static函数没有this指针
static成员是类的组成部分,但不是任何对象的组成部分,因此static成员函数没有this指针,通过static成员显式或隐式引用this指针会造成编译错误。
static成员函数不能为const:将成员函数声明为const就是保证不会修改该函数所属的对象,而static成员函数并不关联对象。static也不能声明为虚函数。
(3)static数据成员的定义
static 数据成员必须在类定义体外定义,它不能像普通数据成员一样通过构造函数进行初始化,而是在定义时初始化,如下:
1 class Account 2 { 3 private: 4 static double interestRate; 5 static double initRate(); 6 }; //类体外定义 double Account::interestRate = initRate();
上面的代码中,在类体外调用类的私有成员函数initRate()对static数据成员interestRate进行定义,由于interestRate的作用域位于类中,所以可以访问类的私有成员,所以上面调用initRate()进行定义是合法的。
注意:体外定义时不要加上static关键字。
虽然一般的非const的static数据成员被要求在类体外定义,但是const static成员则可以在类体中进行初始化,即使如此,还是需要在类的定义体外对该static数据进行定义(VS2010中是不需要的),但是不能再指定初始值,否则编译器会报重定义,多次初始化错误:
1 class Account 2 { 3 private: 4 static const int period = 30; 5 }; 6 7 //类体外进行定义 8 const int Account::period;
(4)static成员独立类对象而存在
普通成员是给定类的每个对象的组成部分,而static成员不属于任何对象,所以static数据成员类型可以是该成员所属的类类型,而非static成员则被限定只能为其自身类对象的指针或引用:
class Bar { private: static Bar mem1;//ok Bar* mem2;//ok Bar mem3; //error };
static成员可以用作默认实参,非static成员则由于无法提供对象以获取该成员的值而不能作默认实参:
1 class Account 2 { 3 public: 4 void Deal(double rate = iRate); 5 private: 6 static const double iRate = 0.001; 7 };