C++中的静态成员(静态成员函数和静态数据成员)属于类所有,不属于类的对象,与普通的成员相比,静态成员无this指针。
静态成员变量
不同的对象占用不同的内存,这就使不同对象的成员变量相互独立,互不影响。给定两个对象a
和b
,假设我们修改了a.a
,b.a
并不会受到影响。
如果我们想要在多个对象之间共享一个数据,这就用到了静态成员变量。
- 静态成员变量是一种特殊的成员变量,被static修饰。
- 只能被定义一次,储在全局常量区,不占用对象的储存空间这就意味静态成员不随对象的创建而分配内存,也不随对象的销毁而释放内存。
- 被同类的全体成员共享,单静态成员变量只有一个实例存在,与类定义了多少对象无关,
也就是说静态成员是与该类相关的,而不是与类的实例对象相关
静态成员变量不能在类中初始化,因为静态成员变量是被所有的对象所共享,若在类中初始化的话每次创建一个新的对象它的值都要被修改。
静态成员变量不能用初始化列表进行初始化,静态成员变量只能在类外进行初始化,一般缺省值为0。
class A
{
public:
static void print()
{
cout << "x="<<x << endl; //通过公有成员函数访问私有静态数据成员
}
static int z;
private:
static int x;
};
int A::z = 0; //类外初始化
int A::x = 0;//类外初始化
int main()
{
A::print();
cout << "z=" << A::z << endl;//类外直接访问公用的静态数据成员
system("pause");
}
- 静态数据成员只能在类体外初始化;
- 不能在类内初始化或通过构造函数或初始化列表初始化静态数据成员;
- 静态数据成员可以通过对象名引用,也可以通过类名来引用;
- 公共的静态数据成员可以在类外直接引用,也可以通过对象名引用,但私有的静态数据成员只能公用的成员函数引用。
2. 静态成员函数
static不仅可以声明静态成员变量,也可以声明静态成员函数,静态成员函数只能访问静态成员,静态成员函数和外部的其他函数。
像静态成员变量一样,静态成员函数也可以通过对象名和类名来调用
class A
{
public:
A(int x) :_x(x){}
static void print(A a)
{
cout << "x="<<a._x << endl;//正确,静态成员函数不能直接访问非静态数据成员
cout<<"x="<<_x<<endl; //错误
}
private:
int _x;
};
int main()
{
A a(10);
A::print(a);
system("pause");
}
- 由于没有this指针,由此决定了静态成员函数不能直接访问类的非静态数据成员;
- 静态成员函数主要用来访问静态数据成员,而不访问非静态成员;
- 如果一定要访问本类的非静态成员,应该加对象名和成员运算符"."。
3.静态成员函数和普通成员函数的区别
- 静态成员函数没有this指针,只能访问静态成员
- 普通成员函数有this指针,可以访问类中的任意成员
4.静态变量生命周期
静态变量的类型说明符是static。静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量,例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。对于自动变量,它属于动态存储方式。但是也可以用static定义它为静态自动变量,或称静态局部变量,从而成为静态存储方式。由此看来,一个变量可由static进行再说明,并改变其原有的存储方式。
1. 静态局部变量
在局部变量的说明前再加上static说明符就构成静态局部变量。例如:
static int a,b; static float array[5]={1,2,3,4,5};
静态局部变量属于静态存储方式,它具有以下特点:
(1)静态局部变量在函数内定义,但不象自动变量那样,当调用时就存在,退出函数时就消失。静态局部变量始终存在着,也就是说它的生存期为整个源程序。
(2)静态局部变量的生存期虽然为整个源程序,但是其作用域仍与自动变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后,尽管该变量还继续存在,但不能使用它。
(3)允许对构造类静态局部量赋初值。若未赋以初值,则由系统自动赋以0值。
(4)对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值。而对自动变量不赋初值,则其值是不定的。根据静态局部变量的特点,可以看出它是一种生存期为整个源程序的量。虽然离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用,而且保存了前次被调用后留下的值。因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的,但全局变量有时会造成意外的副作用,因此仍以采用局部静态变量为宜。
2.静态全局变量
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。应予以注意。
备注:类在实例化的时候,是通过new关键字来进行的,new时会默认提供一个隐藏的this指针,该指针的作用只要是用来访问实例对象的成员变量的。