单例模式、工厂模式 c++关键字 static

static 关键字的作用:

主要作用在于 控制变量或函数的作用域生命周期以及它们如何被不同部分的程序访问,从而帮助程序员管理内存、避免命名冲突,并实现特定的设计模式(如单例模式)。

  • 1. 静态局部变量:当在一个函数内部声明一个静态局部变量(如下面单例模式示例中的static BoxFactory boxFactory;),这个变量的生命周期将延伸到包含它的函数结束之后。这样的静态局部变量在程序运行期间只会被初始化一次,即使函数被多次调用。它保留了上一次函数调用结束时的值。

  • 2.静态全局变量:在文件作用域声明的静态变量(即在函数外部,但用static修饰),其作用范围限制在定义它的源文件内,即它是“内部链接”的。这意味着其他源文件中的代码不能直接访问这个变量,有助于减少命名冲突并封装数据。

  • 3.静态成员变量:在类声明中使用static声明的成员变量不属于类的任何特定实例,而是属于整个类。所有类实例共享同一个静态成员变量的副本。静态成员变量必须在类定义之外初始化。静态成员可以通过类名直接访问,无需实例化对象

  • 4.静态成员函数:静态成员函数也是类的一部分,但不与类的任何特定实例关联。它们不能访问非静态成员变量(因为非静态成员变量是特定于实例的),但可以访问静态成员变量和其他静态成员函数。静态成员函数同样通过类名直接调用,无需实例化对象

  • 5.静态外部变量声明:在头文件中使用extern和static声明变量,可以让多个源文件共享同一变量的声明,但每个使用该声明的源文件需要有一个独立的定义(没有static),以避免多重定义错误。这种方式主要用于跨文件共享常量或全局数据。

static 关键字示例:

1.静态局部变量

下面代码中有两个函数fun1和fun2,其中fun2中的局部变量b用static关键字修饰成静态局部变量,那么变量b不是在栈区上创建的,而是在静态区上创建的。在静态区上创建的变量,生命周期是全局的,也就是说,静态局部变量的生命周期和程序的生命周期相同
我们分别运行五次fun1()和fun2(),会发现b只会被创建一次,后面执行fun2()函数时由于存储在静态区没有被销毁,所以还是使用的已经存在的b并不会重新创建,理解这一点对单例模式中全局唯一一次类的实例化很关键

void fun1() {int a = 0;a++;printf(" a = %d   | ", a);
}void fun2() {static int b = 0;b++;printf(" b = %d   | ", b);
}void main()
{for (size_t i = 0; i < 10; i++){if (i < 5) fun1();else fun2();}
}

在这里插入图片描述

2.静态全局变量

静态全局变量的例子就不举例了,很多理解,被static修饰的全局变量只能在本cpp文件中访问。

3.静态成员函数,静态成员变量

设计模式中的工厂模式+单例模式很好解释静态成员函数的用法:
下面的代码块有四个类:
我们可以通过工厂类可以实例化圆形 和正方形,但每次用工厂类的时候,我们不需要每次都实例化一个工厂,因此工厂类就用到了单例模式,使工厂在整个系统的生命周期唯一,避免多次创建。
在这里插入图片描述
此外阅读时注意工厂类中getInstance()使用static 修饰,

	static ShapeFactory& getInstance() //静态成员函数{static ShapeFactory instance;  //静态成员变量return instance;}
  • 确保唯一性:通过将getInstance方法声明为静态成员函数,可以不依赖于类的任何实例直接访问。这使得无论何时何地调用getInstance,都只会返回同一个ShapeFactory实例,保证了全局唯一性。
  • 全局访问:静态方法可以在不创建类实例的情况下被调用,因此可以在程序的任何地方访问工厂类的单例,便于统一管理和协调对象的创建过程。
    因此在调用时还可以写成:
int main()
{auto circle = ShapeFactory::getInstance().createShape("Circle");if (circle){circle->draw();}auto square = ShapeFactory::getInstance().createShape("Circle");if (square){square->draw();}return 0;
}
#include <iostream>
#include <iostream>
#include <memory>
using namespace std;// 抽象形状类
class Shape
{
public:virtual ~Shape() {}virtual void draw() const = 0;
};// 圆形类
class Circle : public Shape
{
public:void draw() const override{std::cout << "Drawing Circle" << std::endl;}
};// 正方形类
class Square : public Shape
{
public:void draw() const override{std::cout << "Drawing Square" << std::endl;}
};// 形状工厂类 - 单例模式
class ShapeFactory
{
public:static ShapeFactory& getInstance(){static ShapeFactory instance;return instance;}Shape* createShape(const std::string& shapeType){if (shapeType == "Circle"){Circle* pCircle = new Circle();return pCircle;}else if (shapeType == "Square"){Square* pSquare = new Square();return pSquare;}else{return NULL;}}private:ShapeFactory() = default;								// 私有构造函数ShapeFactory(const ShapeFactory&) = delete;			// 禁止拷贝构造ShapeFactory& operator=(const ShapeFactory&) = delete; // 禁止赋值操作
};int main()
{ShapeFactory& factory = ShapeFactory::getInstance(); // 获取工厂单例auto circle = factory.createShape("Circle");if (circle){circle->draw();}auto square = factory.createShape("Square");if (square){square->draw();}return 0;
}

我们可以通过一下代码来验证工厂类是否在全局中只创建了一次

// 形状工厂类 - 单例模式
class ShapeFactory
{
public:static ShapeFactory& getInstance(){static ShapeFactory instance;return instance;}Shape* createShape(const std::string& shapeType){if (shapeType == "Circle"){Circle* pCircle = new Circle();return pCircle;}else if (shapeType == "Square"){Square* pSquare = new Square();return pSquare;}else{return NULL;}}private:ShapeFactory();// 私有构造函数~ShapeFactory();ShapeFactory(const ShapeFactory&) = delete;			// 禁止拷贝构造ShapeFactory& operator=(const ShapeFactory&) = delete; // 禁止赋值操作
};ShapeFactory::ShapeFactory() {std::cout << "工厂类构造函数" << std::endl;
}ShapeFactory::~ShapeFactory() {std::cout << "工厂析构函数" << std::endl;
}
int main()
{for (int i = 0; i < 5; i++) {ShapeFactory& factory = ShapeFactory::getInstance(); // 获取工厂单例std::cout << "i = " << i << std::endl;}return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/26867.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

区间预测 | Matlab实现EVO-CNN-SVM能量谷算法优化卷积神经网络支持向量机结合核密度估计多置信区间多变量回归区间预测

区间预测 | Matlab实现EVO-CNN-SVM能量谷算法优化卷积神经网络支持向量机结合核密度估计多置信区间多变量回归区间预测 目录 区间预测 | Matlab实现EVO-CNN-SVM能量谷算法优化卷积神经网络支持向量机结合核密度估计多置信区间多变量回归区间预测效果一览基本介绍程序设计参考资…

5.3 Python 闭包函数,递归函数,匿名函数

1. 函数对象 Python中所有的数据都是对象, 函数的值也是一个对象, 通过函数名获取函数对象. 使用函数名也就是使用函数对象, 函数对象加上括号立刻执行函数体代码块. 函数名的其它作用: * 1. 函数名可以作为其它变量的值. * 2. 函数名可以作为其它函数的参数. * 3. 函数名可以…

搜索与图论:染色法判别二分图

搜索与图论&#xff1a;染色法判别二分图 题目描述参考代码 题目描述 输入样例 4 4 1 3 1 4 2 3 2 4输出样例 Yes参考代码 #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N 100010, M 200010;int n, m; i…

多款可观测产品全面升级丨阿里云云原生 5 月产品月报

云原生月度动态 云原生是企业数字创新的最短路径。 《阿里云云原生每月动态》&#xff0c;从趋势热点、产品新功能、服务客户、开源与开发者动态等方面&#xff0c;为企业提供数字化的路径与指南。 趋势热点 &#x1f947; 阿里云云原生产品负责人李国强&#xff1a;推进可…

《Brave New Words 》9.1 AI 世界中的就业

Part IX: Work and What Comes Next 第九部分&#xff1a;工作及其未来发展 The one who plants trees, knowing that he will never sit in their shade, has at least started to understand the meaning of life. —Rabindranath Tagore 种树的人&#xff0c;虽然知道他永远…

如何舒适的使用VScode

安装好VScode后通常会很不好用&#xff0c;以下配置可以让你的VScode变得好用许多。 VScode的配置流程 1、设置VScode中文2、下载C/C拓展&#xff0c;使代码可以跳转3、更改编码格式4、设置滚轮缩放5、设置字体6、设置保存自动改变格式7、vscode设置快捷代码8、下载插件并学会…

Java多线程面试重点-1

0. 什么是并发&#xff1f;什么是并行&#xff1f; 并发&#xff1a;把时间分成一段一段&#xff0c;每个线程轮流抢占时间段。 如果时间段非常短&#xff0c;线程切换非常快&#xff0c;被称为伪并行。并行&#xff1a;多个线程可以同时运行。 并发与并行造成的影响&#xff…

ARM32开发--IIC软实现

知不足而奋进 望远山而前行 目录 文章目录 前言 开发流程 GD32F4软件I2C初始化 GD32F4软件I2C引脚功能 写操作 读操作 总结 前言 在嵌入式系统开发中&#xff0c;软件实现的I2C通信协议扮演着至关重要的角色。本文将深入探讨如何在GD32F4系列微控制器上实现软件I2C功能…

深入浅出 Go 语言的 GPM 模型(Go1.21)

引言 在现代软件开发中&#xff0c;有效地利用并发是提高应用性能和响应速度的关键。随着多核处理器的普及&#xff0c;编程语言和框架如何高效、简便地支持并发编程&#xff0c;成为了软件工程师们评估和选择工具时的一个重要考量。在这方面&#xff0c;Go 语言凭借其创新的并…

Python的Pillow(图像处理库)非常详细的学习笔记

Python的Pillow库是一个非常强大的图像处理库。 安装Pillow库&#xff1a; 在终端或命令行中输入以下命令来安装Pillow&#xff1a; pip install pillow 安装后查看是否安装成功以及当前版本 pip show Pillow 升级库&#xff1a; pip install pillow --upgrade 一些基…

u-boot(六) - 详细启动流程

一&#xff0c;u-boot启动第一阶段 1&#xff0c;启动流程 ENTRY(_start) //arch/arm/lib/vectors.S ----b resets //arch/arm/cpu/armv7/start.S --------b save_boot_params ------------b save_boot_params_ret //将cpu的工作模式设置为SVC32模式&#xff08;即管理模式&a…

NodeClub:NodeJS构造开源交流社区

NodeClub&#xff1a; 连接每一个想法&#xff0c;NodeClub让社区更生动- 精选真开源&#xff0c;释放新价值。 概览 NodeClub是一个基于Node.js和MongoDB构建的社区系统&#xff0c;专为开发者和社区爱好者设计。它提供了一套完整的社区功能&#xff0c;包括用户管理、内容发…

Mongodb在UPDATE操作中使用$push向数组中插入数据

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第69篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题&#xff0c;欢迎在文章下面点个赞&#xff0c;或者关…

qt dll编写和调用

dll编写 新建项目 头文件 #ifndef LIB1_H #define LIB1_H#include "lib1_global.h"class LIB1_EXPORT Lib1 { public:Lib1(); };//要导出的函数&#xff0c;使用extern "C"&#xff0c;否则名称改变将找不到函数extern "C" LIB1_EXPORT int ad…

探索未来边界:前沿技术引领新纪元

目录 引言 一、人工智能与深度学习&#xff1a;智慧生活的引擎 1.医疗应用 2.智能家居 3.自动驾驶 二、量子计算&#xff1a;解锁宇宙的密钥 1.量子比特示意图 2.量子计算机实物图 3.分子模拟应用 三、生物技术&#xff1a;生命科学的革新 1.CRISPR-Cas9基因编辑图 2.合成生…

buuctf----warmup_csaw_2016

进来医院先来一套常规检查 啥保护都没,看大佬说基本栈溢出 CT一看 OK cat flag 更喜欢了 40060D 找到地址 get也来了,稳啦! 0x80-0x40 8 根据上道题的exp from pwn import * ghust remote("node5.buuoj.cn",27229) addr 0x40060D payload bA * 0x40 bB*8…

C++设计模式——Bridge桥接模式

一&#xff0c;桥接模式简介 桥接模式是一种结构型设计模式&#xff0c;用于将抽象与实现分离&#xff0c;这里的"抽象"和"实现"都有可能是接口函数或者类。 桥接模式让抽象与实现之间解耦合&#xff0c;使得开发者可以更关注于实现部分&#xff0c;调用…

具有不确定性感知注意机制的肺结节分割和不确定区域预测| 文献速递-深度学习结合医疗影像疾病诊断与病灶分割

Title 题目 Lung Nodule Segmentation and UncertainRegion Prediction With an Uncertainty-Aware Attention Mechanism 具有不确定性感知注意机制的肺结节分割和不确定区域预测 01 文献速递介绍 肺结节分割在肺癌计算机辅助诊断&#xff08;CAD&#xff09;系统中至关重…

java Springboot网上音乐商城(源码+sql+论文)

1.1 研究目的和意义 随着市场经济发展&#xff0c;尤其是我国加入WTO &#xff0c;融入经济全球化潮流&#xff0c;已进入国内外市场经济发展新时期&#xff0c;音乐与市场联系越来越紧密&#xff0c;我国音乐和网上业务也进入新历史发展阶段。为了更好地服务于市场&#xff0…