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

news2024/9/22 7:04:31

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.coloradmin.cn/o/1821286.html

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

相关文章

Unity Protobuf+RPC+UniTask

远程过程调用&#xff08;RPC&#xff09;协议详解 什么是RPC协议RPC的基本原理RPC的关键组件RPC的优缺点Protobuf函数绑定CallEncodeRecvDecodeSocket.Send和Recv项目地址 什么是RPC协议 远程过程调用&#xff08;Remote Procedure Call&#xff0c;简称RPC&#xff09;是一种…

配置Windows客户端连接iSCSI设备

1、运行iSCSI发起程序 控制面板–>系统和安全–>管理工具–>iSCSI发起程序。 2、更改客户端iqn属性 3、点击连接&#xff0c;就会在本次磁盘新加一款硬盘。 4、通过格式化新建卷就可使用该硬盘。

eBay测评,自养号应该如何做?

测评自养号就是自己搭建国外的服务器和IP环境&#xff0c;实现自己注册eBay的买家账号&#xff0c;通过电脑端环境一台电脑就可以无限养号&#xff0c;一次可以开十几个窗口同时浏览下单&#xff0c;每个窗口都是独立的环境&#xff0c;一账号一环境一IP一卡 买家账号掌握在卖…

ARM32开发--存储器介绍

知不足而奋进 望远山而前行 目录 文章目录 前言 存储器分类 RAM ROM EEPROM Flash 总结 前言 在现代计算机系统中&#xff0c;存储器扮演着至关重要的角色&#xff0c;不仅影响着数据的存取速度和稳定性&#xff0c;还直接关系到计算机系统的性能和应用场景的选择。存…

ARM32开发--IIC时钟案例

知不足而奋进 望远山而前行 目录 文章目录 前言 目标 内容 需求 开发流程 移植驱动 修改I2C实现 测试功能 总结 前言 在现代嵌入式系统开发中&#xff0c;移植外设驱动并测试其功能是一项常见的任务。本次学习的目标是掌握移植方法和测试方法&#xff0c;以实现对开…

热门开源大模型项目推荐

一&#xff1a;开源大模型热门项目推荐 NNI&#xff1a;由微软发布的开源AutoML工具包&#xff0c;支持神经网络超参数调整。最新版本对机器学习生命周期的各个环节做了全面支持&#xff0c;包括特征工程、神经网络架构搜索(NAS)、超参调优和模型压缩。适用于各种机器学习项目&…

三极管的厄利效应(early effect)

詹姆斯M厄利(James M. Early)发现的现象&#xff0c;厄利效应&#xff08;英语&#xff1a;Early effect&#xff09;&#xff0c;又译厄尔利效应&#xff0c;也称基区宽度调制效应&#xff0c;是指当双极性晶体管&#xff08;BJT&#xff09;的集电极&#xff0d;射极电压VCE改…

DETR实现目标检测(二)-利用自己训练的模型进行预测

1、图片预测&#xff08;CPU&#xff09; 关于DETR模型训练自己的数据集参考上篇文章&#xff1a; DETR实现目标检测(一)-训练自己的数据集-CSDN博客 训练完成后的模型文件保存位置如下&#xff1a; 准备好要预测的图片&#xff1a; 然后直接调用模型进行预测&#xff0c;并设…

基于springboot实现入校申报审批系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现入校申报审批系统演示 摘要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装入校申报审批系统软…

ChatGPT中文镜像网站分享

ChatGPT 是什么&#xff1f; ChatGPT 是 OpenAI 开发的一款基于生成预训练变换器&#xff08;GPT&#xff09;架构的大型语言模型。主要通过机器学习生成文本&#xff0c;能够执行包括问答、文章撰写、翻译等多种文本生成任务。截至 2023 年初&#xff0c;ChatGPT 的月活跃用户…

CV每日论文--2024.6.14

1、ICE-G: Image Conditional Editing of 3D Gaussian Splats 中文标题&#xff1a;ICE-G&#xff1a;3D 高斯斑点的图像条件编辑 简介&#xff1a;近年来,出现了许多技术来创建高质量的3D资产和场景。然而,当涉及到这些3D对象的编辑时,现有方法要么速度慢、要么牺牲质量,要么…

基于Python+OpenCV高速公路行驶车辆的速度检测系统

简介&#xff1a; 基于Python和OpenCV的高速公路行驶车辆的速度检测系统旨在实时监测高速公路上的车辆&#xff0c;并测量它们的速度。该系统可以用于交通监控、道路安全管理等领域&#xff0c;为相关部门提供重要的数据支持。 系统实现&#xff1a; 视频流输入&#xff1a;系…

Java项目中使用OpenCV检测人脸的应用

Java项目中使用OpenCV检测人脸的应用 一、准备工作 将下载好的opencv的jar包放在项目的根目录下&#xff0c;可以新建一个lib的文件夹&#xff0c;将其放在此处&#xff1b; 在pom文件中引入&#xff1a; <profiles><!-- 生产环境 --><profile><id>…

用智能插件(Fitten Code: Faster and Better AI Assistant)再次修改vue3 <script setup>留言板

<template><div><button class"openForm" click"openForm" v-if"!formVisible">编辑</button><button click"closeForm" v-if"formVisible">取消编辑</button><hr /><formv-i…

Java求职季 必备知识脑图 收藏起来 !!!

Java初中级知识脑图 面试超实用 1.Git 下载链接 导图下载地址 &#xff1a; https://mm.edrawsoft.cn/mobile-share/index.html?uuid31d00742157057-src&share_type1 2.JUC 下载链接 https://mm.edrawsoft.cn/mobile-share/index.html?uuid6c0be457444921-src&s…

自动控制:滑模控制(Sliding Mode Control, SMC)

自动控制&#xff1a;滑模控制(Sliding Mode Control, SMC) 滑模控制&#xff08;Sliding Mode Control, SMC&#xff09;是一种在处理非线性系统时非常有效的控制技术。它通过驱动系统状态达到并保持在特定的滑模面附近&#xff0c;来实现控制目标。本文将介绍滑模控制的基本…

MES系统助力制造业数字化转型

一、MES系统的定义和功能 MES&#xff08;Manufacturing Execution System&#xff09;即制造执行系统&#xff0c;是一种可层级化管理生产活动的软件系统。它可以实现对生产过程全面的监控、调度、控制和优化&#xff0c;提高生产的效率、质量和安全性。MES系统具有以下几个主…

工作手机安全管理平台建设方案

第一章 项目背景 移动互联网的时代&#xff0c;各个行业在在推进移动办公和掌上办公&#xff0c;通过智能手机、平板电脑等进行线上办公&#xff0c;这样能提高了企业人员的办公效率&#xff0c;从而为客户提供更及时的服务。 在移动办公提高了工作人员办公效率的同时&#xf…

这三款使用的视频、图片设计工具,提供工作效率

Videograp Videograp是一款专注于视频生成的工具&#xff0c;特别适合需要快速剪辑和编辑视频的用户。Videograp具备以下特点&#xff1a; 影音比例转换&#xff1a;Videograp支持调整视频的分辨率和比例&#xff0c;使其更适合不同的播放环境和设备。 AI快剪&#xff1a;该工…

牛客链表刷题(一)

目录 题目一&#xff1a;反转链表 代码&#xff1a; 题目二&#xff1a;链表内指定区间反转 代码&#xff1a; 题目一&#xff1a;反转链表 代码&#xff1a; import java.util.*;/** public class ListNode {* int val;* ListNode next null;* public ListNode(int …