一、修饰普通变量
1.局部变量
用法:static + 变量类型 + 变量名
内存中的位置:静态存储区
初始化:未经初始化的局部静态变量会被自动初始化为 0(自动对象的值是任意的,除非他被显示初始化)。
作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。但
是当局部静态变量离开作用域后,并没有销毁,而是仍然驻留在内存当中,只不过我们不能再对它
进行访问,直到该函数再次被调用,并且值不变。
即:static修饰的局部变量的生命周期被改变(栈区---->静态存储区),但是作用域不变。
2.全局变量
用法:static + 变量类型 + 变量名
内存中的位置:静态存储区
初始化:未经初始化的全局静态变量会被自动初始化为 0(自动对象的值是任意的,除非他被显示初始化)。
作用域:全局静态变量在声明他的文件之外是不可见的,准确地说是从定义之处开始,到文
件结尾。
注意:static修饰全局变量,并未改变其存储位置及生命周期,而是改变了其作用域,使当前文件外的源文件无法访问该变量。
3.静态函数
用法:函数返回类型前加 static
函数的定义和声明在默认情况下都是 extern 的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。
注意:
二、修饰类变量
1.成员变量
静态成员是类的所有对象中共享的成员,而不是某个对象的成员。对多个对象来说,静态数据成员只存储一处,供所有对象共用,
包括派生类的对象。因此,static成员必须在类外进行初始化,而不能在构造函数内进行初始化,
不过也可以用const修饰static数据成员在类内初始化(初始化列表)。
2.成员函数
静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员。因此,
对静态成员的引用不需要用对象名。
静态成员函数没有this指针,因此
-
静态成员函数只能调用静态成员变量,无法直接调用非静态成员变量。
- 如果静态成员函数中要引用非静态成员时,可通过对象来引用。
静态成员变量和函数均可通过类名 + 作用域的方式访问
class A {
public:
A(int s, int ss){
a = s;
b = ss;
}
public:
static void dis() {
//cout << a << endl; //error,非static成员
cout << b << endl; //ok,static成员
}
public:
int a;
static int b;
};
int A::b = 8888; //类外初始化
int main() {
cout << A::b << endl; //8888
A::dis(); //ok,static成员变量和函数可以通过 类名 + 作用域 直接调用
return 0;
}
注意:不可以同时用const和static修饰成员函数。
C++编译器在实现const的成员函数的时候为了确保该函数不能修改类的实例的状态,会在函数中添加一个隐式的参数const this*。但当一个成员为static的时候,该函数是没有this指针的。也就是说此时const的用法和static是冲突的。
总结
-
对于函数定义和代码块之外的变量声明,static 修改标识符的链接属性,由默认的 external 变为 internal,作用域和存储类型不改变,这些变量只能在声明它们的源文件中访问。
-
对于代码块内部的变量声明,static 修改标识符的存储类型,由自动变量改为静态变量,作用域和链接属性不变。这种变量在程序执行之前就创建,在程序执行的整个周期都存在。
-
对于被 static 修饰的普通函数,其只能在定义它的源文件中使用,不能在其他源文件中被引用。
-
对于被 static 修饰的类成员变量和成员函数,它们是属于类的,而不是某个对象,所有对象共享一个静态成员。静态成员通过<类名>::<静态成员>来使用。