一. static 关键字概述

static 关键字的作用体现在以下两个方面

  • 实现数据共享,节约内存
  • 保持封装性,避免命名冲突

static 可以作用的对象

  • C语言:局部变量、全局变量、函数
  • C++:类的成员变量和成员函数

static 关键字的生命周期

程序开始时 或 类开始加载时就会为 static 修饰的变量分配空间(它们存储在数据段),进程结束时才会释放空间。

  • 定义静态局部变量和静态全局变量创建时可以不给初值,默认初始值为0
  • 成员函数可以定义在类内部,也可以在外部定义(在外部定义时不能加 static 关键字)
  • 成员变量必须在类外部定义其值(在外部定义时不能加 static 关键字)

二. 修饰静态普通函数

使用方法:在函数返回值类型前添加 static

效果:被修饰的函数只能在当前的文件中使用,在其他文件中可以定义相同名称的函数。

解释说明

在一个项目中我们创建两个源文件:main.cpp 和 demo.cpp,如果我们在两个文件中定义了相同名称的函数的话编译就会报错:

在这里插入图片描述

正确的方法是在一个文件中去定义函数,在另一个文件中去引入该函数的声明,这样两个文件中都可以使用这个函数:
在这里插入图片描述

如果我们只想让 Fun() 函数在定义它的文件内使用,而不能被外部文件使用,应该怎么做到呢?我们只需给这个函数加上 static 关键字即可,这样该函数就变为静态函数,其作用域由之前的整个项目内的文件都可访问变为了只能在本文件内被访问:
在这里插入图片描述

demo.cpp 中的 Fun() 函数变为静态函数之后,我们可以在 main.cpp 中声明去定义同名 Fun() 函数了,二者作用域不同,互不影响:
在这里插入图片描述

三. 修饰全局静态变量

使用方法:在全局变量前添加 static

作用效果:把全局变量的作用域缩小为只能在本文件内访问,生命周期不变。

解释说明

1、数据位于静态区,自动初始化为0,仅用于本文件,其他文件可以定义相同名称变量。

在这里插入图片描述

2、全局变量在外部文件采用 extern 可以访问,但全局静态变量不可访问,它的作用域缩小为仅在本文件内可以访问。

在这里插入图片描述

四. 局部静态变量

使用方法:在局部变量前添加 static

作用效果

  • 把局部变量的生命周期延长(生命周期和全局变量一样,随进程一起结束),但作用域不变。
  • 局部变量(栈区)在函数执行结束后,将会被释放,但静态局部变量会一直存在,直到程序执行结束。

解释说明

1、数据位于静态区,不初始化的话默认值为0

在这里插入图片描述

2、数据存储在静态区,变量只被初始化一次,之后不再初始化,数值在每次调用时根据语句功能进行修改。

在这里插入图片描述

五. 类的静态成员变量

使用方法:在类的成员变量前添加 static,该静态成员变量只能在类的内部定义,外部声明。

作用效果:实现多对象的数据共享,即多对象的静态成员变量只占一处内存,由该类的所有对象共用。

解释说明

1、成员变量必须在类外部定义其值(在外部定义时不能加static关键字),在访问时可以通过类名直接访问

class A
{
public:
	static int n;
};

// 类的静态成员变量只能在类外部定义(类外部定义时不能加static关键字),类内部声明
int A::n = 10;

int main()
{
	// 1、通过示例对象访问静态成员变量
	A a;
	cout << a.n << endl;// 输出10
	
	// 2、因为类的静态成员变量是所有该类的对象所共享的
	//    所以也可以通过类名直接访问
	cout << A::n <<endl;// 输出10
	return 0;
}

2、静态成员变量必须定义设初值,否则编译不通过

在这里插入图片描述

3、静态成员变量的访问也是受类的访问限定符得限制的

在这里插入图片描述

六. 类的静态成员函数

使用方法:在类的成员函数返回值类型前加 static

作用效果:为多对象提供服务,函数内部无法访问属于类对象的非静态成员,只能访问类的静态成员。

解释说明

1、类的内部、外部都可以定义类的成员函数

在这里插入图片描述

2、普通成员函数隐含this指针在第一个参数,它指向对象本身,因而可以访问对象的成员;而静态成员函数没有this指针,所以:

  • 非静态成员函数可以任意地访问静态成员和非静态成员。
  • 静态成员函数不能访问非静态成员,只能访问静态成员。

3、static 成员函数不能被 virtual 修饰,static 成员不属于任何对象或实例,所以加上 virtual 没有任何实际意义;静态成员函数没有 this 指针,虚函数的实现是为每一个对象分配一个vptr指针,而vptr是通过this指针调用的,所以不能为virtual;

虚函数的调用关系:this->vptr->ctable->virtual function

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐