1 静态成员变量
1.1 定义静态成员变量
-
关键字
static
可以用于说明一个类的成员 -
静态成员提供了一个同类对象的共享机制
-
把一个类的成员说明
static
时,无论这个类有多少对象被创建,这些对象共享这个static
成员 -
静态成员局部于类,他不是对象的成员
如同下图所示,对于同类定义出来的对象
A,B,C,D
其中成员变量是ch
是每个对象自己特有,但是静态成员变量s是全体对象共用,只要有一个对象修改了这个s
的值,则全部相同类定义的对象中的s
都发生改变。
如同上图所示,对于同类定义出来的对象A,B,C,D
其中成员变量是ch
是每个对象自己特有,但是静态成员变量s是全体对象共用,只要有一个对象修改了这个s
的值,则全部相同类定义的对象中的s
都发生改变。
#include<iostream.h>
class counter
{
public :
counter (int a)
{
mem = a;
}
int mem; //公有数据成员
static int Smem ; //公有静态数据成员
} ;
![image](uploading...)
int counter :: Smem = 1; //初始值为1
void main()
{ counter c(5);
int i ;
for( i = 0 ; i < 5 ; i ++ )
{ counter::Smem += i ;
cout << counter::Smem << '\t' ; //访问静态成员变量方法2
}
cout<<endl; cout<<"c.smem="<<c.Smem<<endl; //访问静态成员变量方法1
cout<<" c.mem="<<c.mem<<endl;
}
1.2 静态成员函数
- 静态成员变量冠以关键词
static
- 静态成员变量是不依赖类数据结构的共同操作
- 在类外调用静态成员变量是有 类名::作为限定词,或者通过对象进行调用
举个例子
class X
{
public:
static void printfID()
{
// count<<id<<endl; 错误做法
count<<s_id<<endl; //正确做法
}
private:
int id;
static int s_id;
}
//使用static 修饰的变量是属于整个类,所有的对象都可以共用
其中 // count<<id<<endl;
是错误,原因如下图所示:
对于每一个对象都存在一个独有的id
变量,但是对于static
修饰的函数是共用,如果使用static
函数通用普通的的成员变量就无法区分是哪一个对象的id
变量。
1.3使用static的好处(参考)
-
第一个好处肯定就是占用内存小,不需要对每一个对象都分配函数空间。
-
可以实现某些特殊的设计模式:如
Singleton
; -
可以封装某些算法,比如数学函数,如
ln,sin,tan
等等,这些函数本就没必要属于任何一个对象,所以从类上调用感觉更好,比如定义一个数学函数类Math,调用Math::sin(3.14);如果非要用非静态函数,那就必须:Math math; math.sin(3.14);
行是行,只是不爽:就为了一个根本无状态存储可言的数学函数还要引入一次对象的构造和一次对象的析构,当然不爽。而且既然有了对象,说不得你还得小心翼翼的定义拷贝构造函数、拷贝赋值运算符等等,对于一些纯算法的东西显然是不合适的。 -
由于没有this指针,可以把某些系统API的回调函数以静态函数的形式封装到类的内部。因为系统API的回调函数通常都是那种非成员函数(孤立函 数),没有this指针的。比如你可以在类的内部写一个线程函数供
CreateThread
创建线程用,如果没有静态函数,那么这种回调函数就必须定义成 全局函数(非静态成员函数指针无法转换成全局函数指针),从而影响了OO的“封装性”。 -
总之,从OOA/OOD的角度考虑,一切不需要实例化就可以有确定行为方式的函数都应该设计成静态的。
以上只是一些基本的考虑,并不是绝对的。绝对东西的只有一点:“静态函数不需要实例化就可以被调用,不会也不可以调用或操纵非静态成员”。记住这一点,那么实际编程中何时需要用,何时适合用,自然就更容易作出决定了。