单例模式、工厂模式 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;
}
 

相关文章:
单例模式、工厂模式 c++关键字 static
static 关键字的作用: 主要作用在于 控制变量或函数的作用域、生命周期以及它们如何被不同部分的程序访问,从而帮助程序员管理内存、避免命名冲突,并实现特定的设计模式(如单例模式)。 1. 静态局部变量:当…...
基于文本和图片输入的3D数字人化身生成技术解析
随着虚拟现实、增强现实和元宇宙等技术的飞速发展,对高度逼真且具有表现力的3D数字人化身的需求日益增长。传统的3D数字人生成方法往往需要依赖大量的3D数据集,这不仅增加了数据收集和处理的成本,还限制了生成的多样性和灵活性。为了克服这些挑战,我们提出了一种基于文本提…...
C语言 | Leetcode C语言题解之第150题逆波兰表达式求值
题目: 题解: int evalRPN(char** tokens, int tokensSize) {int n tokensSize;int stk[(n 1) / 2];memset(stk, 0, sizeof(stk));int index -1;for (int i 0; i < n; i) {char* token tokens[i];if (strlen(token) > 1 || isdigit(token[0])…...
API安全性的重要性及实施策略
在当今日益互联的世界中,API(应用程序编程接口)成为连接不同软件系统的关键桥梁。随着API的使用越来越广泛,其安全性问题也日益凸显。一个不安全的API可能会使企业数据和用户信息面临严重的风险。因此,确保API的安全性…...
现在Java行情不好可以转.net吗?
转向.NET开发可能是一个选择,但要注意以下几点。我这里有一套编程入门教程,不仅包含了详细的视频 讲解,项目实战。如果你渴望学习编程,不妨点个关注,给个评论222,私信22,我在后台发给你。 技术转…...
大文件word生成的处理与解决策略
前言 对于简单word文档的生成导出,java已经有着很多技术来进行处理,在有着相对固定的格式样板下,采用word模板导出相对会是比较好的选择。但是当数据量且包含大量图片后,采用模板导出就显得无力了,模板的缺点是无法应…...
unity3d:GameFramework+xLua+Protobuf+lua-protobuf,与服务器交互收发协议
概述 1.cs收发协议,通过protobuf序列化 2.lua收发协议,通过lua-protobuf序列化 一条协议字节流组成 C#协议基类 CSPacketBase,SCPacketBaseC#用协议基类 proto生成的CS类,基于这两个基类。分别为CSPacketBase是客户端发送至服…...
二刷算法训练营Day30 | 回溯算法(6/6)
目录 详细布置: 1. 回溯总结 2. 332. 重新安排行程 3. 51. N 皇后 4. 37. 解数独 详细布置: 1. 回溯总结 回溯是递归的副产品,只要有递归就会有回溯,所以回溯法也经常和二叉树遍历,深度优先搜索混在一起&#x…...
【车载AI音视频电脑】200万像素迷你一体机
产品主要特点: -设备安装方便简洁,可通过3M胶直接将设备粘 贴到车前挡风玻璃上 -支持IE预览,手机,PAD实时预览, 支持电脑客 户端实时预览功能 -内置2路模拟高清, 每路均可达到200万像素。另 外可扩充2路1080P模拟…...
齐普夫定律在循环神经网络中的语言模型的应用
目录 齐普夫定律解释公式解释图与公式的关系代码与图的分析结论 使用对数表达方式的原因1. 线性化非线性关系2. 方便数据可视化和分析3. 降低数值范围4. 方便参数估计公式详细解释结论 来自:https://zh-v2.d2l.ai/chapter_recurrent-neural-networks/language-model…...
如何在Android Studio上发布Flutter应用
发布Flutter应用到Android平台是一个多步骤的过程,涉及配置应用、生成签名密钥、配置Gradle文件、构建发布版本APK等步骤。本文将详细介绍这些步骤,帮助你顺利发布Flutter应用。 1. 准备你的应用 在发布之前,确保你的应用在开发环境中运行良…...
C++ 字符串处理4-根据指定的分隔符将字符串分割为多个子串根据指定的分隔符将多个子串连接成一个字符串
1. 关键词 C 字符串处理 分割字符串 连接字符串 跨平台 2. strutil.h #pragma once#include <string> #include <vector>namespace cutl {/*** brief The type of vector strings used in this library.**/using strvec std::vector<std::string>;/*** b…...
微信小程序请求request封装
公共基础路径封装 // config.js module.exports {// 测试BASE_URL: https://cloud.chejj.cn,// 正式// BASE_URL: https://cloud.mycjj.com };请求封装 // request.js import config from ../config/baseUrl// 请求未返回时的loading const showLoading () > wx.showLoadi…...
Web前端不挂科:深入探索与实战指南
Web前端不挂科:深入探索与实战指南 在数字化时代的浪潮中,Web前端开发已成为一项炙手可热的技能。然而,对于许多初学者来说,如何避免在Web前端课程中挂科却成为了一道难题。本文将从四个方面、五个方面、六个方面和七个方面&…...
Golang | Leetcode Golang题解之第149题直线上最多的点数
题目: 题解: func maxPoints(points [][]int) (ans int) {n : len(points)if n < 2 {return n}for i, p : range points {if ans > n-i || ans > n/2 {break}cnt : map[int]int{}for _, q : range points[i1:] {x, y : p[0]-q[0], p[1]-q[1]if…...
京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设
京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设 京准电钟 NTP时间同步服务器助力水库水坝水利自动化建设 水库大坝监测系统主要包括渗流监测系统、流量监测系统、雨量监测系统、沉降监测系统组成。每一个监测系统由监测仪器及自动化数据采集装置(内置通信装…...
程序员应该具备什么职业素养?
程序员应该有什么职业素养? 作为一个程序员,拥有以下职业素养是非常重要的: 扎实的技术功底:作为程序员,首先要具备扎实的技术基础,包括编程语言、算法、数据结构等方面的知识,能够熟练地解决问…...
linux 安装sftp及使用sftp上传和下载
一、centos7 安装sftp 1.安装 OpenSSH 服务: sudo yum install openssh-server2.启动 SSH 服务,并设置为开机启动: sudo systemctl start sshd sudo systemctl enable sshd3.创建一个新用户,用于SFTP连接(替换your_…...
AI虚拟试穿技术:开启高保真、多场景、多样化服装组合的试穿应用
随着电子商务的快速发展,消费者对于在线购物体验的要求越来越高。特别是在服装领域,消费者渴望能够在购买前直观地了解服装的试穿效果。传统的虚拟试穿技术虽然已有一定的发展,但在不同场景下的高保真度和鲁棒性方面仍面临挑战。为此,我们研发了一种全新的AI虚拟试穿技术,…...
数栈xAI:轻量化、专业化、模块化,四大功能革新 SQL 开发体验
在这个数据如潮的时代,SQL 已远远超越了简单的查询语言范畴,它已成为数据分析和决策制定的基石,成为撬动企业智慧决策的关键杠杆。SQL 的编写和执行效率直接关系到数据处理的速度和分析结果的深度,对企业洞察市场动态、优化业务流…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...
