【C++】static静态关键字

在这里插入图片描述


个人主页 :阿然成长日记 点击可跳转
个人专栏: 数据结构与算法C语言进阶C++
不能则学,不知则问,耻于问人,决无长进

文章目录

  • 一、static的概念
  • 二、static引入
  • 三、static详解
  • 四、静态和非静态的访问关系
  • 五、面试题

一、static的概念

【概念】:声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。

二、static引入

我们来看一道题目:

面试题:实现一个类,计算程序中创建出了多少个类对象

首先,分析一下可以知道我们去实例化出一个对象的时候,无非是调用构造或者是拷贝构造,或者是通过一些传参返回的方式去构造对象。这样的话,我们知道必须要使用一个全局的变量来保存记录值。
对于这道题也有两种解决方案:
1️⃣方法一:在全局定义变量

#include

int count = 0;
class A {
public:
	A()
	{
		count++;
	}
	A(const A& a)
	{
		count++;
	}
};

void func(A a)
{
	count++;
}
int main()
{
	A aa1;
	A aa2(aa1);

	func(aa1);
	std::cout << count << std::endl;
	return 0;
}

下面是调试动图:
【C++】static静态关键字_第1张图片
通过调试,可以清楚的看到哪些地方使用了构造以及拷贝构造。
【注意】:这里定义的count会和std库里发生冲突。所以在使用的时候,为了防止报错,我们就要正确的使用命名空间。养成良好习惯,不要使用using namesapce std;全部展开。

❌此种方法缺乏安全性。
因为count是一个全局变量,那么它的生命周期就是从定义开始到main函数结束的时候销毁,这任何地方都是可以访问到的,并且它还不具有常性可以做任意修改,这其实也就缺乏了一定的安全性。

三、static详解

2️⃣方法二:使用static修饰

在C++中就引入了这样一个东西,把count作为类的成员变量。这样写,count是属于每个对象的。

class A {
public:
	A()
	{
		count++;
	}
	A(const A& a)
	{
		count++;
	}
private:
	static int count;
};

此时,我们给加上static,这个count就是属于这个类的,创建出的所有对象也都共享这个count;也就引出了如下特性:
1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区

2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明

class A {
public:
	A()
	{
		count++;
	}
	A(const A& a)
	{
		count++;
	}
private:
	static int count;
};
int count = 0;

但是我们发现会出现下面问题,这又是为什么呢?
【C++】static静态关键字_第2张图片

原来是我在外部定义时,没有 指明count的出处。此时,我们只需要加上作用域即可。

int A::count = 0;

【补充】为什么不能在类中直接声明+定义呢?

  • 上面刚学习了构造函数的初始化列表,在类内直接定义是因为缺省值是给到构造函数的初始化列表用的,初始化列表初始化的是非静态成员,是属于当前对象的;而静态成员是属于所有对象的,是共有的,需要在全局区域定义。

3. 静态成员也是类的成员,受public、protected、private 访问限定符的限制
运行发现出现下面问题,
在这里插入图片描述

4. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
如下:

std::cout << aa1.count << std::endl;
std::cout << A::count << std::endl;
std::cout << A().count << std::endl;

尤其注意第三种,使用匿名对象 来访问。

5. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
这点通过以前的学习已经是十分清楚,静态成员函数是全局的,在静态区没有this指针,但普通的成员变量都是属于当前对象的,需要通过this指针来访问。

四、静态和非静态的访问关系

静态成员函数不能调用非静态成员函数。
静态成员函数内部可以调用静态的成员变量或者函数
非静态成员函数可以调用类的静态成员函数

五、面试题

1.全局静态变量

  • 在全局变量前加上关键字 static,全局变量就定义成一个全局静态变量
  • 初始化:末经初始化的全局静态变量会被自动初始化为0(自动对象的值是任意的,除非他被显式初始化)
  • 存储位置:数据段(静态区、全局区)
  • 作用域:全局静态变量在声明他的文件之外是不可见的,准确地说是从定义之处开始,到文件结尾。缩小范围

2.局部静态变量

  • 在局部变量之前加上关键字 static,局部变量就成为一个局部静态变量。
  • 初始化:末经初始化的全局静态变量会被自动初始化为0(自动对象的值是任意的,除非他被显式初始化)
  • 存储位置:数据段(静态区、全局区)
  • 作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。但是当局部静态变量离开作用域后,并没有销毁,而是仍然驻留在内存当中,只不过我们不能再对它进行访问,直到该函数再次被调用,并且值不变

3.静态函数

利用关键字extern,可以在一个文件中引用另一个文件中定义的变量或者函数

  • 在函数返回类型前加 static,函数就定义为静态函数。函数的定义和声明在默认情况下都是 extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。

4.类的静态成员变量

  • 在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,即保证了安全性。因此,静态成员是类的所有对象中共享的成员,而不是某个对象的成员。对多个对象来说,静态数据成员只存储一处,供所有对象共用

5.类的静态函数

  • 类静态成员函数和静态类成员变量一样,它们都属于类的静态成员,它们都不是对象成员,没有this指针。因此,对静态成员的引用不需要用对象名。
  • 是一个公共的函数。

你可能感兴趣的:(C++基础,c++,开发语言)