static可以分为类/结构体外和类/结构体内使用,在类外的作用主要是隐藏,其次因为static变量存放在静态存储区,所以它具备持久性和默认值0。在类和结构体之外使用static,意味着声明的变量或函数只会在被声明的C++文件中看到。换句话说,静态变量或函数意味着,当需要将这些函数或变量与实际定义的符号链接时,链接器不会在这个翻译单元的作用域之外,寻找那个符号定义。就像声明了一个私有变量,其他翻译单元无法看见这个静态变量,链接器在全局作用域也无法看见这个变量。
1. 隐藏
对于static变量和函数均可。
所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。如果加了static,就会对其它源文件隐藏。利用这一特性,在不同源文件中定义同名函数或变量也不会产生冲突。
// a.cpp
int a = 10; // 全局变量
static int b;
void msg()
{
cout<<a<<""<<b;
// main.cpp
int main()
{
int a=20; // 会冲突,链接会出现错误,全局变量可见
int b=100; // 不会冲突,因为b在a.cpp中是静态变量,被隐藏了,在main.cpp中看不到
return 0;
}
2. 有记忆性
static变量会默认初始化并具有记忆性,并且只会初始化一次。虽然在局部范围内声明,但static变量的生命周期和全局变量一样,只是只能在局部范围内才能访问。换句话说,如果作为static局部变量在函数内定义,它的生存期为整个源程序,但是其作用域仍与自动变量相同,只能在定义该变量的函数内使用该变量。退出该函数后, 尽管该变量还继续存在,但不能使用它。
void print()
{
static int count; // 默认初始化为0
count++;
std::cout << count << std::endl;
}
int main()
{
// count = 10; 编译无法通过,报错count没有声明
// 证明count只能在print函数作用域内使用
print(); // 输出 1
print(); // 输出 2
print(); // 输出 3
return 0;
}
3. 类内使用
类或结构体内部的静态变量或方法,意味着该变量或方法与类的所有实例共享内存。换句话说,在某个实例中改变了静态变量,会反映在所有实例中。静态方法一样,无法访问类实例,即静态方法无须通过实例调用。**静态方法不能访问非静态变量。**静态成员变量和函数都是有访问权限的。
类的静态成员函数是属于整个类而非类的对象,所以它没有this指针,这就导致 了它仅能访问类的静态数据和静态成员函数。
静态成员变量:
- 所有对象共享一份数据
- 在编译阶段分配内存
- 类内声明,类外初始化(C++17可以使用inline在类内初始化)
静态成员函数:
- 所有对象共享同一个函数
- 静态成员函数只能访问静态成员变量
- 静态成员函数不能是const,不能使用this指针
- 不能将静态成员函数定义为虚函数
class A
{
static int a; //类内声明
inline static int count{10}; //C++17标准
}
int A::a = 0; //类外初始化