本文讨论C++类中的static成员的一些特性。我们知道静态成员的特点事它只属于类本身,不属于类的任何一个对象。在类加载的时候就初始化了。那么由这一个特性我们可以得出很多其他的一些特性:

1, 调用方式方面的特点。我们调用静态成员的时候,不需要依赖于一个具体的类对象(当然也可以用对象去调用静态成员),可以直接用“类名::静态成员”这种方式去调用。

2, 没有this指针。我们知道C++的每个类都包含一个隐藏的成员函数——this指针,用来指向当前对象。而且这个this指针默认就是const的(top-level的const,有关top-level和low-level const的可以看我的博文《Top-Level和Low-Level const》),即这个this里面就是存的这个对象的地址,不可以改变。而静态变量不属于任何一个对象,所以它没有this指针。

3, 不能将静态成员函数声明为const的。首先我们看下边的一个成员函数的声明:

class A 
{
public:
    ...
    string get_something() const 
    { 
        return this->some_member; 
    } 
    ...
}

我们注意到里面的成员函数get_something的参数列表后面有一个const。那么这个const代表什么含义呢?其实就是修饰隐藏的this指针的。前面已经说了,this指针默认是top-level的const,即它本身不可以改变。但是有时候,我们也不想让成员函数可以通过this指针改变它指向的对象,即我们也想让她同时是low-level const的,这时候我们就在参数列表后面加一个const就可以了。更多信息可以参见我的博文《C++的const成员函数和this指针以及mutable关键字》。因为这个const是修饰this指针的,而静态成员没有this指针,所以我们不能将静态成员函数声明为const。

4, 对于static成员函数,如果我们在类内部声明,然后在类外部实现,那只需要在声明的时候加上static关键字就可以了,在定义的时候不必且不能再加static关键字,否则会报错。我个人觉得这个有点苛刻了。

5, 不使用类的构造函数。我们知道类的构造函数实在初始化对象的时候使用的,既然静态成员不属于任何一个变量,自然也就不使用类的构造函数了。而且对于静态成员的初始化我们一定要小心——我们不能在类中初始化静态成员,因为我们一般是将类写在头文件中的,而头文件可能被多个源文件包含。也就是说,如果在类中初始化静态变量,那可能造成重复初始化的错误。一般最好的方式是在实现类的成员函数的cpp文件中去初始化静态成员。

6, 可以用不完全类型(incomplete type,比如只有前向声明,还没有具体实现的类)定义静态成员,但不可以定义非静态成员(指针和引用例外)。

当然,这里只是列举出了一部分static的特性,由于static成员属于类,而不属于对象这个大的特点导致它还有很多区别于非静态成员的特点,我们使用的时候需要注意。

最后,举一个《C++ Primer》上面的例子:假设有一个Account类,用来表示银行账户,那么每个账户都会有自己的所有者,以及账户所存储的金额,但是利率每个账户应该都是一样的。那么这个时候,我们就可以将利率定义为静态变量。看下面的代码:

// Account.h

/*
 * Account.h
 *
 *  Created on: 2015年10月26日
 *      Author: Allan
 */

#ifndef ACCOUNT_H_
#define ACCOUNT_H_

#include <iostream>
#include <string>

class Account
{
public:
    Account() = default;      // C++11新特性
    ~Account();

public:
    void calculate() { amount += amount * interestRate; }

    static double rate() { return interestRate; }
    static void rate(double);

private:
    static double initRate() { return 0.053; };

private:
    std::string owner;
    double  amount = 0;
    static double interestRate;
};

#endif /* ACCOUNT_H_ */

// Account.cpp
/*
 * Account.cpp
 *
 *  Created on: 2015年10月26日
 *      Author: Allan
 */

#include "Account.h"

/*
 * static 关键字只需要在类中声明的时候使用即可
 */
void Account::rate(double newRate)
{
    interestRate = newRate;
}

double Account::interestRate = initRate();