对于某些类,我们可能需要定义1个全局对象。比如,我们想定义一个整形数据,来记录一个类的某个函数调用的次数,或者统计一共创建了多少个这个类的对象。之前只能通过全局对象来实现,但是这样做有一个明显的缺点:全局对象会破坏类的封装特性,任何代码都可以修改这个全局对象,这是很不安全的。
因此,C++中引入了类静态成员,这个成员用static修饰。有一点念需要明确:static对象并不是某个类的成员,而是这个类共有的。如果我们把它设为私有成员,那么类外的函数就不能对它访问,从而实现了封装。
先看一个简单的程序:
class Test { public: Test(){cnt++;} static void display() { cout<<cnt<<endl; } static int cnt; static const int one = 1; }; int Test:: cnt = 0; const int Test::one; int main() { Test tst1; tst1.display(); Test tst2; tst2.display(); tst2.cnt = 10; Test tst3; tst3.display(); Test::cnt = 100; Test tst4; tst4.display(); cout<<Test::one<<endl; return 0; }
程序中Test类声明了一个static成员cnt,可以用来记录Test对象的的个数。第一次打印结果为1,第二次为2.由于我把它设为公有有成员,所以在类外也可以修改它,让它“看起来”跟类的普通成员差不多,但是修改以后,第3次次打印的结果就变成11了,这说明上一次对类static成员的修改对于这一次使用类依然有影响。当然,我们也可以使用作用域操作符::来修改它。
对于数据,我们可以定义它为static,对于函数也可以。此时这个函数也是属于类的,而不属于某个具体的对象。所以,static成员函数没有this指针。当然,static完全可以在类内声明,而在类外定义,此时,声明时加上static,而定义时就不用加上static了。
还有一点需要注意,static数据成员必须在类外部定义,而且只能定义一次,也不能通过构造函数初始化它!所以最好把它放在对应头文件的cpp文件中,即把它与成员的非内联函数的定义放在一起!它的定义的方法跟其他的类成员相同:先定义类型,再指定是哪个类中的,最后才是定义的语句,需要注意的是定义时不能加static。
上面的定义方法有一种特例,就是整型的const static成员,它是在类的定义体中初始化:static const int one = 1;但是这里的初始化本质上还是声明,而它的定义依然在类外进行,只不过不用指定初值而已:const int Test::one;