static关键字的作用
- 修饰局部变量
static修饰局部变量时,使得被修饰的变量成为静态变量,存储在静态区。存储在静态区的数据生命周期与程序相同,在main函数之前初始化,在程序退出时销毁。(无论是局部静态还是全局静态)
- 修饰全局变量
全局变量本来就存储在静态区,因此static并不能改变其存储位置。但是,static限制了其链接属性。被static修饰的全局变量只能在该函数定义的文件或者包含该函数定义的文件中被调用访问(即改变了作用域)。
- 修饰函数
static修饰函数使得函数只能在该函数定义的文件或者包含该函数定义的文件中被调用。对于静态函数,声明和定义需要放在同一个文件中。
注意:如果声明和定义没有放在同一个文件中,有可能报错,看下面代码
//include.h
#pragma once
#include<iostream>
void function1();
static void function2();
//include.cpp
#include"include.h"
void function1()
{
std::cout << "function1" << std::endl;
function2();
function2();
function2();
}
static void function2()
{
static int num = 0;
num = num + 1;
std::cout << "function2 num:" << num << std::endl;
}
//main.cpp
#include"include.h"
int main()
{
function2();
function2();
function2();
cout << "=====" << endl;
function1();
cout << "=====" << endl;
}
编译时,报错。因为 静态函数会在 include.obj 和 main.obj中定义两个 不相干的 同名静态函数,但main.cpp只包含了声明 没有函数体
修改将 include.cpp中的function2函数定义拷贝到 include.h中后
//include.h
#pragma once
#include<iostream>
void function1();
static void function2();
static void function2()
{
static int num = 0;
num = num + 1;
std::cout << "function2 num:" << num << std::endl;
}
//include.cpp
#include"include.h"
void function1()
{
std::cout << "function1" << std::endl;
function2();
function2();
function2();
}
编译通过,打印结果,发现在main函数中调用3次function2 和在function1中调用3次function2的结果一样,并没有累加起来,说明function2函数分别在 main.obj 和 include.obj中定义了同名 不相干的函数。
- 修饰成员变量
用static修饰类的数据成员使其成为类的全局变量,会被类的所有对象共享,包括派生类的对象,所有的对象都只维持同一个实例。 因此,static成员必须在类外进行初始化(初始化格式:int base::var=10;),而不能在构造函数内进行初始化,不过也可以用const修饰static数据成员在类内初始化。
- 修饰成员函数
用static修饰成员函数,使这个类只存在这一份函数,所有对象共享该函数,不含this指针,因而只能访问类的static成员变量。静态成员是可以独立访问的,也就是说,无须创建任何对象实例就可以访问。例如可以封装某些算法,比如数学函数,如ln,sin,tan等等,这些函数本就没必要属于任何一个对象,所以从类上调用感觉更好,比如定义一个数学函数类Math,调用Math::sin(3.14);还可以实现某些特殊的设计模式:如Singleton;
最重要的特性:隐藏
当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏。
不可以同时用const和static修饰成员函数。
C++编译器在实现const的成员函数的时候为了确保该函数不能修改类的实例的状态,会在函数中添加一个隐式的参数const this*。但当一个成员为static的时候,该函数是没有this指针的。也就是说此时const的用法和static是冲突的。我们也可以这样理解:两者的语意是矛盾的。static的作用是表示该函数只作用在类型的静态变量上,与类的实例没有关系;而const的作用是确保函数不能修改类的实例的状态,与类型的静态变量没有关系。因此不能同时用它们。