static关键字的介绍主要从以下几个方面进行:
1. 静态局部变量
先看一个例子:
#include <iostream>
using namespace std;
void fun();
int main()
{
for (int i = 0; i < 3; i++)
fun();
system("pause");
return 0;
}
void fun()
{
// 将只被声明一次
static int x;
cout << "x = " << x << endl;
x++;
}
最后的打印结果是
x = 0
x = 1
x = 2
由上面的例子,我们可以列举出静态局部变量的特点:
(1) 静态局部变量如果未被显示初始化,则默认初始化为0;
(2) 静态局部变量只被声明一次,以后调用不再初始化;
(3) 静态变量在 “静态存储区”分配内存,其生命周期为整个程序,虽然静态局部变量的作用域只限于当前局部区域。
2. 静态全局变量
举个简单的例子,当一个工程包含两个源文件时:
// 文件1,data.cpp
int num1 = 1;
static int num2 = 2;
// 文件2,demo.cpp
#include <iostream>
using namespace std;
extern int num1;
extern int num2;
int main()
{
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
system("pause");
return 0;
}
上述程序编译将无法通过,报错为:
main.obj : error LNK2001: 无法解析的外部符号 "int num2"
当把int num2前面的extern去掉后,编译成功,输出结果为:
num1 = 1
num2 = 0
分析上面的程序,可以得到静态全局变量的一些特点:
(1) 普通全局变量可以通过“extern”关键字实现任意文件共享;而静态全局变量的作用域只限声明文件,不可以同其它文件共享;
(2) 静态全局变量使得我们可以在其它文件声明同样名称的变量而不担心冲突;
3. 静态函数
和静态全局变量相似,静态函数的作用域仅限于其声明文件,其他源文件无法调用,且可以无冲突地声明同样名称的函数。
注意,是源文件,如果是Include头文件形式则没有用。
4. 静态类成员变量
还是先看一个例子:
//fun.h文件
#include <iostream>
using namespace std;
class fun
{
public:
fun()
{
x++;
cout << "x = " << x << endl;
};
static int x;
};
// main.cpp文件
#include <iostream>
#include "fun.h"
using namespace std;
int fun::x = 0;
int main()
{
fun fun1;
fun fun2;
cout << "x = " << fun::x << endl;
system("pause");
return 0;
}
输出结果为:
x = 1
x = 2
x = 2
静态类成员变量同静态局部变量的特点相似,但也有一些不同点
(1) 静态类成员变量必须在类外初始化。 上述程序,如果注释掉 int fun::x = 0;
则会报错:
error LNK2001: 无法解析的外部符号 "public: static int fun::x"
(2) 静态类成员变量同样常驻全局数据区,不占用类对象开辟的空间,所有类的实例化对象共享该数据;
(3)public静态类成员变量可以通过 class_name::var_name 的形式直接访问,普通类成员变量必须通过实例化对象才可以访问;
5. 静态类成员函数
静态类成员函数的作用也是限制了作用域:
(1) 静态类成员函数仅限于访问其它静态类成员变量和静态类成员函数;
(2)与静态成员变量相似,可以通过class_name::fun_name 来直接调用类成员函数;
(3)普通类成员函数存在一个隐藏的this指针指向当前实例化对象,而静态函数不存在,因此调用速度可能略快。