static:
作为c/c++的关键字之一,具有多种含义和应用,static 关键字可用于声明变量、函数、类数据成员和类函数。默认情况下,在所有块的外部定义的对象或变量具有静态持续时间和外部链接。 静态持续时间意味着,在程序启动时分配对象或变量,并在程序结束时释放对象或变量。 外部链接意味着,变量的名称在用于声明变量的文件的外部是可见的。 相反,内部链接意味着,名称在用于声明变量的文件的外部是不可见的。
在以下情况下,可使用 static 关键字:
在文件范围(全局和/或命名空间范围)内声明变量或函数时,static 关键字将指定变量或函数具有内部链接。 在声明变量时,变量具有静态持续时间,并且除非您指定另一个值,否则编译器会将变量初始化为 0。
在函数中声明变量时,static 关键字将指定变量将在对该函数的调用中保持其状态。
在类声明中声明数据成员时,static 关键字将指定类的所有实例共享该成员的一个副本。 必须在文件范围内定义静态数据成员。 声明为 const static 的整型数据成员可以有初始值设定项。
在类声明中声明成员函数时,static 关键字将指定类的所有实例共享该函数。 由于函数没有隐式 this 指针,因此静态成员函数不能访问实例成员。 若要访问实例成员,请使用作为实例指针或引用的参数来声明函数。
不能将联合成员声明为静态的。 但是,全局声明的匿名联合必须是显式声明的 static。
全局变量:
在函数外部定义的变量。它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序。在函数中使用全局变量,应该做全局变量说明。只有在函数内经过说明的全局变量才能使用。但在一个函数之前定义的全局变量,在该函数内使用可以不再加以说明。
静态全局变量:
定义在函数体外,用来修饰全局变量,未经初始化的静态全局变量会被自动初始化为0;在申明静态全局变量的文件以外是不可见的。不同的源文件中都可以使用同一个全局变量,但当定义为静态全局变量之后,其作用域知存在于当前源文件。
举例:
变量max
在static.cpp
中定义为静态全局变量,因此无法在main.cpp
中使用,运行会提示 “无法解析的外部符号”。
//main.cpp
#include <iostream>
#include "static.h"
using namespace std;
int a = 5; //全局变量
int main()
{
extern int max; //申明静态全局变量,运行失败,想用max,则max需定义为全局变量,而不是静态全局变量
cout << "max: " << max << endl;
fun();
return 0;
}
//static.pp
#include <iostream>
#include "static.h"
using namespace std;
static int max = 1000000; //静态全局变量,要想在main.cpp中使用,需定义为全局变量
//int max = 1000000;
void fun(void)
{
int min = 11;
cout << "min:" << min << endl;
}
//static.h
#include <iostream>
void fun(void);
运行结果:
无法编译成功
想使用static.cpp
中的全局变量max
,则需要定义为全局变量,而不是静态全局变量。
局部变量:
在程序中只在特定过程和函数中可以访问的变量,是相对于全局变量而言的。在C等面向过程语言中,局部变量可以和全局变量重名,但是局部变量会覆盖全局变量。在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。
静态局部变量:
定义在函数体内的变量加上static修饰符,它的存在意义是随着第一次函数的调用而初始化,但却不随着函数的调用结束而销毁。因此静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值。
举例:
#include <iostream>
using namespace std;
void test(void)
{
int a = 10; // 局部变量
static int b = 10; //静态局部变量
a++;
b++;
cout << "a:" << a << ", b: " << b << endl;
}
int main()
{
test();
test();
test();
test();
test();
test();
return 0;
}
运行结果,可以看到局部变量和静态局部变量的差异。
函数:
c/c++函数是c/c++程序的基本组成单位,用于实现特定的功能或计算。
静态函数:
在函数定义前加上修饰符static,作用和静态全局变量类似;函数的定义和生命在默认状态下都是extern的,但静态函数只是在申明他的文件当中可见,不能被其余文件所用。
举例:
//main.cpp
#include <iostream>
#include "static.h"
using namespace std;
int main()
{
fun();
test();//报错,无法调用static.cpp中的静态函数
return 0;
}
//static.cpp
#include <iostream>
#include "static.h"
using namespace std;
//普通函数
void fun(void)
{
int min = 11;
cout << "min:" << min << endl;
}
//静态函数,无法在其他文件中使用该函数
static void test(void)
{
int min = 1111;
cout << "min:" << min << endl;
}
//static.h
#include <iostream>
void fun(void);
static void test(void);
运行结果:
可以看到,在main函数中调用test()函数,会提示声明未定义。
类的静态成员:
修饰class的数据成员,这种数据成员的生存期大于class的对象;静态数据成员是每个class有一份,普通数据成员是每个实例有一份,因此静态数据成员也叫类变量,普通数据成员也叫实例变量。
类的静态成员函数:
在成员函数前加上static就变成了静态成员函数;静态成员函数不能访问非静态成员函数或数据成员,但非静态可以访问静态。
因为静态是属于类的,无法感知创建的对象,所以它对你对象的函数或者数据是一无所知的,所以它没办法调用;而反过来,创建的对象是对类是可以感知的,所以是可以调用类函数和类成员的。
静态成员函数能够继承和覆盖,但没法是虚函数。
#include <iostream>
using namespace std;
class A
{
public:
static int a; //类的静态成员变量
static int get_a();//类的静态成员函数
int b;
int get_b();
};
int A::a = 100; //静态成员变量可以在类的外部直接定义
//int A::b = 1000; //普通成员变量在类的外部定义失败
int A::get_a()
{
return a; //类的静态成员函数只能访问类的静态成员变量
//return b + a; //静态成员函数无法调用普通成员变量
}
int A::get_b()
{
return b + a;//普通成员函数可以调用静态成员变量
}
int main(void)
{
cout << "a: " << A::get_a() << endl; //不需要类的实例,也可以调用类的静态成员函数
A m;
m.b = 90;
m.a = 100000;
cout << m.get_a() << endl;
cout << m.get_b() << endl;
cout << m.a << endl;
return 0;
}
运行结果: