C++基础知识2:static关键字
本文目的
简单的介绍一下static在不同地方使用的作用,在全局,在函数,在类里面的使用,以及相关应用举例
前置与关联知识点
- 类基础
- 未命名空间
- 不完全数据类型
static关键字简介
static就是一个关键字,没啥简介的
static在不同地方使用的意义
1. static修饰文件中全局变量以及函数的作用
参考《Primer C++》术语表p723
使用关键字static声明的全局变量/函数仅仅对当前文件有效,失去了外部链接属性
但是在当前C++版本中已经不再使用,而是使用未命名的命名空间实现该作用了。
使用场景:一些需要避免命名冲突,以及不希望
1.1 全局变量使用static修饰
失去外部链接属性,无法extern到其他文件使用
示例代码如下,在solution.cpp里面定义并声明静态变量static_val,同时在main去使用该变量
//solution.cpp
static int static_val = 1;
//main.cpp
extern int static_val;
链接的时候会报错找不到
undefined reference to `static_val'
删掉static之后就可以了
1.2 全局函数使用static修饰
失去外部链接属性,无法被声明(而非定义)处之外的其他文件调用了,也不能extern。
示例代码如下,在solution.cpp里面定义并声明静态函数static_fun,同时在main去使用该函数
//solution.cpp
static int static_fun()
{
return 1;
}
//main.cpp
extern int static_fun();
链接的时候会报错找不到
undefined reference to `static_fun'
删掉extern就可以了
ps:加入头文件之后再使用对应的函数而不是extern,也是会报错的
2. static修饰函数中局部变量作用
- 作用域:该变量的作用域仍然在函数的块的范围内
- 生命周期:变量在堆区生成,程序结束才销毁
- 在第一次经过该变量定义语句的时候初始化,后续调用不会在初始化,而是维持原有值
3. static在类中的使用
static在类中可以修饰函数也可以修饰数据成员,效果不同。
3.1 类的静态数据成员与定义
参考《Primer C++》7.6 类的静态成员p268
有的时候类需要一些成员和类本身直接相关,而不是和对象保持关联
通过static可以使得其与类本身关联在一起。 可以是常量,引用,指针
被static修饰的数据成员为该类全对象所共有,生成在堆区,不同的对象调用函数访问的都是同一个数据成员
关于类的数据成员定义
参考《Primer C++》7.6 类的静态成员p270
静态数据成员不属于类的任何对象,不能由构造函数初始化,必须要在外部定义每个静态成员
可以在外部定义的时候初始化(不显式初始化也会隐式帮你初始化了),外部不需要再添加static修饰符
初始化的时候可以使用类的静态成员函数,无论公私有
下面给出一种有意思的初始化方式例子
class Solution{
public:
static int sta_val;//声明
static int initval()
{
cout<<sta_val;
return 2022;
};
};
int Solution::sta_val = initval();//定义并且初始化
这里sta_val调用静态成员函数inittval()进行初始化,但是initval()又用到了sta_val,会发生什么呢?
是可以正常运行的,输出是0;debug会发现一开始int Solution::sta_val之后还没执行函数前,这个变量就已经可以观察到了(意
味着已经分配了空间),并且默认初始化了是0,执行完initval之后变成2022。
静态成员类内初始化(例外)
参考《Primer C++》7.6 类的静态成员p270
const的静态类型可以在类内初始化,这里暂时不展开讨论
3.2 类的静态函数成员
参考《Primer C++》7.6 类的静态成员p270
静态成员函数也不和任何对象绑定在一起,可以使用对象对其进行访问,也可以直接使用作用域运算符访问
静态成员函数的特点,只能使用类的静态成员,不存在this指针
不能声明为const
3.3 静态数据成员可以是不完全类型
参考《Primer C++》7.6 类的静态成员p271
静态数据成员可以是不完全数据类型
非静态数据成员则不行,除非是指针或者引用
如何理解?个人理解如下(还不是非常理解)
- 指针和引用本质上都可以当作是32位地址,在计算类的空间占用的时候是固定的。
- 非静态数据成员如果是不完全数据类型,则还没有确定的空间大小,无法确定好空间大小。
- 静态成员为什么可以我不太清楚。
- 静态数据成员是自己所在类的类型的话,不会出现套娃导致计算大小无穷大的情况,止于自身。
3.4 静态数据成员可以作为默认实参
这个很好理解,因为他不属于某个对象,而是所有类共有的也存在于堆区,作为默认实参也没啥问题。
一般数据成员的值和对象挂钩,会引发一些错误。
5. 其他
如有则补充
参考文献
《Primer C++》术语表p723
《Primer C++》7.6 类的静态成员p268-p271