static概述

static时用于声明静态变量或者方法的关键字,在编写代码时,往往使用static

static在cpp中分为两个场景使用,一个是在类的外部使用,一个是在类的内部使用。

  • 在类的外部使用:

当我们在类的外部使用时,static往往是临时性的,当我们在两个文件中同时定义了全局变量后会出现重复定义的报错,此时使用static可以将全局变量或者函数变为局部变量或者函数,也就是作用域的改变,在编译的obj文件中,如果使用了static,那么连接器在当下的编译单元即.obj文件以外的地方寻找定义,这个方法或者函数只能在当下的文件里可见,即作用域仅限于当前所在的文件中。如果此时我们使用extern去寻找另外一个文件的用static定义的函数或者文件那么会无法找到。

具体实例如下:

1
2
3
4
5
//文件1.cpp
int val=1;
//文件2.cpp
int val=1;
//此时报错,相同的全局变量名字只能有一个

使用static修改后如下

1
2
3
4
5
//文件1.cpp
int val=1;
//文件2.cpp
static int val=1;
//程序会正常运行

但是如果我们使用extern来声明,此时我们是找不到的

如下演示:

1
2
3
4
5
//文件1.cpp
extern int val;
//文件2.cpp
static int val=1
//此时会无法找到定义的val变量
  • static在类以内的地方使用:

static在类中使用基本都表示一个特定的东西。意味着这个方法或者变量都只有一个实例,如果任意一个实例改变了这个量那么所有的实例中这个量也会随之改变,相当于实现了所有同种类中实例的”共享“,所以在类实例中引用静态变量没有意义,如同全局实例一样,静态方法相同,不能访问类的实例,即使是在静态方法的内部也不可以访问类的实例,而静态方法的调用需要用::来调用

静态成员例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//使用struct是默认成员都为public权限
struct T
{
static int val1,val2;
void Print()
{
std::cout << x << "," << y << std::endl;
}
}

int main()
{
T t;
//当使用static后以下方法赋值会报错
t={1,2};
t.val1=1;
t.val2=2;
}

静态方法例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
struct T
{
static int val1,val2;
void Print()
{
std::cout << x << "," << y << std::endl;
}
}
//此时的val1和val2属于整个T类型的全局变量,我们定义时要用如下方法
//此处也可以直接赋值
int T::val1;
int T::val2;

int main()
{
T t,t1;
//当使用static后以下方法赋值会报错
t={1,2};
//当为静态后只有在上述10,11行定义后才能在这里赋值
t.val1=1;
t.val2=2;
//当在t1中修改了这两个值后,在t中也会随之改变,即全局在T类中的变量只有一个
t1.val1=3;
t1.val2=4;
//代码修正的实质如下:
T::val1=3;
T::val2=4;
}

如果方法也进行静态调用例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct T
{
static int val1,val2;
static void Print()
{
std::cout << x << "," << y << std::endl;
}
}
//此时的val1和val2属于整个T类型的全局变量,我们定义时要用如下方法
//此处也可以直接赋值
int T::val1;
int T::val2;

int main()
{
T::val1=1;
T::val2=2;
//此时方法的使用也只能使用::
T::Print();
}

如果使用了非静态的变量和静态方法,那么方法就无法访问变量,因为静态方法无法访问非静态变量例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct T
{
int val1,val2;
static void Print()
{
//在编译器中,下方的x,y会报错,也就是静态方法没有类实例
std::cout << x << "," << y << std::endl;
}
}

int main()
{
T t;
t.val1=1;
t.val2=2;
//此时方法使用不变:
T::Print();
}

上述中静态方法和非静态方法的区别是静态方法没有一个指向实例方法的指针,使得静态方法如同在类外部的使用,无法识别val1和val2的内容,而非静态方法则是本身存在指向实例内部的指针,可以直接调用其中的参数。


资料参考:

youtube上the cherno的cpp系列教学