C++笔记之智能指针和单例、依赖注入结合使用

C++笔记之智能指针和单例、依赖注入结合使用

code review!

文章目录

  • C++笔记之智能指针和单例、依赖注入结合使用
    • 例1.一个类不使用单例,另一个类使用单例
    • 例2.两个类都使用单例,并且通过getInstance()传入类的实例
    • 例3.std::make_unique不能访问私有的构造函数
    • 例4.不通过友元,通过静态成员函数在类外部调用类私有的构造函数

在这里插入图片描述

例1.一个类不使用单例,另一个类使用单例

在这里插入图片描述

运行
在这里插入图片描述

代码

#include <iostream>
#include <memory>class Logger {
private:Logger() {}  // 私有构造函数,防止外部实例化public:static Logger& getInstance() {static Logger instance;  // 静态局部变量确保只有一个实例return instance;}void log(const std::string& message) {std::cout << "Log: " << message << std::endl;}
};class Service {
private:std::shared_ptr<Logger> logger;public:Service(std::shared_ptr<Logger> logger) : logger(logger) {}void doSomething() {logger->log("Service is doing something.");}
};int main() {// 在依赖注入的方式下,创建 Service 实例并传入 Logger 实例Service service(std::make_shared<Logger>(Logger::getInstance()));// 使用 Service 实例service.doSomething();return 0;
}

例2.两个类都使用单例,并且通过getInstance()传入类的实例

在这里插入图片描述

运行
在这里插入图片描述

代码

#include <iostream>
#include <memory>class Logger {private:Logger() {} // 私有构造函数,防止外部实例化public:static std::shared_ptr<Logger> getInstance() {static std::shared_ptr<Logger> instance = std::shared_ptr<Logger>(new Logger());return instance;}void log(const std::string &message) {std::cout << "Log: " << message << std::endl;}
};class Service {private:std::shared_ptr<Logger> logger;Service(const std::shared_ptr<Logger> &logger) : logger(logger) {}public:static std::shared_ptr<Service> getInstance(const std::shared_ptr<Logger> &logger) {static std::shared_ptr<Service> instance = std::shared_ptr<Service>(new Service(logger));return instance;}void doSomething() {logger->log("Service is doing something.");}
};int main() {// 创建 Logger 实例(智能指针管理)std::shared_ptr<Logger> logger = Logger::getInstance();// 创建 Service 实例并传入 Logger 实例std::shared_ptr<Service> service = Service::getInstance(logger);// 使用 Logger 实例logger->log("Logging from main");// 使用 Service 实例service->doSomething();return 0;
}

例3.std::make_unique不能访问私有的构造函数

在这里插入图片描述

编译报错:
在这里插入图片描述

这段代码存在一些小问题:

Service 类的 getInstance 方法中,你使用了 std::make_unique 来创建一个 Service 实例,但是 Service 的构造函数是私有的,不能直接使用 make_unique。你应该改用 std::shared_ptr<Service>(new Service(logger)) 来创建实例,就像在 Logger 类中的 getInstance 方法中一样。

代码

#include <iostream>
#include <memory>class Logger {private:Logger() {} // 私有构造函数,防止外部实例化public:static std::shared_ptr<Logger> getInstance() {static std::shared_ptr<Logger> instance = std::shared_ptr<Logger>(new Logger());return instance;}void log(const std::string &message) {std::cout << "Log: " << message << std::endl;}
};class Service {private:std::shared_ptr<Logger> logger;Service(const std::shared_ptr<Logger> &logger) : logger(logger) {}public:static std::shared_ptr<Service> getInstance(const std::shared_ptr<Logger> &logger) {static std::shared_ptr<Service> instance = std::make_unique<Service>(logger);return instance;}void doSomething() {logger->log("Service is doing something.");}
};int main() {// 创建 Logger 实例(智能指针管理)std::shared_ptr<Logger> logger = Logger::getInstance();// 创建 Service 实例并传入 Logger 实例std::shared_ptr<Service> service = Service::getInstance(logger);// 使用 Logger 实例logger->log("Logging from main");// 使用 Service 实例service->doSomething();return 0;
}

例4.不通过友元,通过静态成员函数在类外部调用类私有的构造函数

在这里插入图片描述

运行
在这里插入图片描述

将实例的创建和初始化封装在了名为 createInstance 的公共静态成员函数中。这个函数在类的外部被调用时,会调用私有构造函数创建一个实例,并返回一个指向这个实例的智能指针。

通过这种方式,你不需要将 std::make_unique 声明为友元函数,也不需要使用特定的友元声明。而是通过公共静态成员函数间接地在类的外部创建实例,从而绕过了直接访问私有构造函数的问题。

构造函数不是静态成员,它们属于实例化的过程,而不是类本身的静态成员。

在C++中,构造函数不是静态成员,它们是用于创建类的实例的特殊成员函数。私有构造函数意味着不能在类的外部直接调用它来创建实例。这是单例模式的一个关键概念,它确保只有一个实例被创建。

而使用公共静态成员函数(如 createInstance)的优势在于,它可以在类的外部创建实例。这是因为静态成员函数不依赖于特定实例,所以它们可以在没有创建对象的情况下被调用。通过在公共静态成员函数中调用私有构造函数,你可以在类的外部创建类的实例。

所以,使用公共静态成员函数解决单例模式中私有构造函数访问问题的关键在于,它提供了一种通过类的内部机制(即静态成员函数)来间接创建实例的方式,绕过了私有构造函数不能直接在外部调用的限制。

代码

#include <iostream>
#include <memory>class Dependency {public:void doSomething() {std::cout << "Dependency is doing something." << std::endl;}
};class Singleton {private:Singleton() { /* 构造函数私有化 */}static std::unique_ptr<Singleton> instance;std::unique_ptr<Dependency> dependency; // 保存依赖项的指针public:// 创建 Singleton 实例的公共静态函数static std::unique_ptr<Singleton> createInstance() {return std::unique_ptr<Singleton>(new Singleton);}// 获取 Singleton 实例的公共静态函数static Singleton &getInstance() {if (!instance) {instance = createInstance();                           // 创建实例instance->dependency = std::make_unique<Dependency>(); // 初始化依赖项}return *instance;}void useDependency() {dependency->doSomething();}// 其他成员函数
};// 初始化静态成员变量
std::unique_ptr<Singleton> Singleton::instance = nullptr;int main() {// 创建 Singleton 实例std::unique_ptr<Singleton> singleton = Singleton::createInstance();// 使用注入的依赖项进行操作singleton->useDependency();return 0;
}

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

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

相关文章

5.基于多能互补的热电联供型微网优化运行

MATLAB代码链接&#xff1a;基于多能互补的热电联供型微网优化运行 MATLAB代码&#xff1a;基于多能互补的热电联供型微网优化运行 关键词&#xff1a;多能互补 综合需求响应 热电联产 微网 优化调度 参考文档&#xff1a;《基于多能互补的热电联供型微网优化运行》基本完全…

【云原生】Docker的数据管理(数据卷、容器互联)

目录 一、数据卷&#xff08;容器与宿主机之间数据共享&#xff09; 二、数据卷容器&#xff08;容器与容器之间数据共享&#xff09; 三、 容器互联&#xff08;使用centos镜像&#xff09; 总结 用户在使用Docker的过程中&#xff0c;往往需要能查看容器内应用产生的数据…

【android12-linux-5.1】【ST芯片】HAL移植后配置文件生成报错

根据ST官方源码移植HAL源码后&#xff0c;执行readme指示中的生成配置文件指令时报错ST_HAL_ANDROID_VERSION未定义之类&#xff0c;应该是编译环境参数问题。makefile文件中是自动识别配置的&#xff0c;参数不祥就会报错&#xff0c;这里最快的解决方案是查询确定自己android…

Docker去除sudo权限

Docker去除sudo权限 使用docker命令时&#xff0c;每次都要sudo提权&#xff0c;否则就会报错提示无权限。 1.查看docker用户组及成员 sudo cat /etc/group | grep docker2.添加docker用户组 sudo groupadd docker3.添加用户到docker组 sudo gpasswd -a ${USER} docker4.增…

selenium Chrome驱动下载地址

Chrome驱动官方最新版下载地址:https://googlechromelabs.github.io/chrome-for-testing/ 有稳定版&#xff0c;开发版等版本可以选择下载 选择 操作系统复制下载链接直接下载

机器学习笔记之优化算法(十九)牛顿法与正则化

机器学习笔记之优化算法——再回首:牛顿法与正则化 引言回顾&#xff1a;经典牛顿法及其弊端牛顿法&#xff1a;算法步骤迭代过程中可能出现的问题正则化 Hessian Matrix \text{Hessian Matrix} Hessian Matrix与相应问题 引言 本节我们介绍经典牛顿法在训练神经网络过程中的迭…

【Flink实战】Flink中的分流

Flink中的分流 在Flink中将数据流切分为多个子数据流&#xff0c;子数据流称为”旁路输出数据流“。 #mermaid-svg-bnbf0HOpEUsgi9nh {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-bnbf0HOpEUsgi9nh .error-icon{…

c++ 实现一个简单的自定义报文协议

思路&#xff1a; 将发送的数据按照长度和body的方式一次放入一个大的buffer中&#xff0c;4个字节存放body长度&#xff0c;后面存放报文&#xff0c;依次放入数据。 后续如果想要存储复杂类型&#xff0c;可以拓展头部信息&#xff0c;比如数据类型等 #include <stdio.h&…

如何在不使用任何软件的情况下将 PDF 转换为 Excel

通常&#xff0c;您可能会遇到这样的情况&#xff1a;您需要的数据不在 Excel 工作表中&#xff0c;而是以数据表形式出现在 PDF 文件中。为了将此数据放入 Excel 工作表中&#xff0c;如果您尝试将数字复制并粘贴到电子表格中&#xff0c;则列/行将无法正确复制和对齐。因此&a…

java八股文面试[Spring]——如何实现一个IOC容器

什么是IOC容器 IOC不是一种技术&#xff0c;只是一种思想&#xff0c;一个重要的面向对象编程的法则&#xff0c;它能指导我们如何设计出松耦合&#xff0c;更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象&#xff0c;从而导致类与类之间高耦合&#xff0c;难于…

从零开始配置Jenkins与GitLab集成:一步步实现持续集成

在软件开发中&#xff0c;持续集成是确保高效协作和可靠交付的核心实践。以下是在CentOS上安装配置Jenkins与GitLab集成的详细步骤&#xff1a; 1.安装JDK 解压JDK安装包并设置环境变量&#xff1a; JDK下载网址 Java Downloads | Oracle 台灣 tar zxvf jdk-11.0.5_linux-x64_b…

关于ros工作空间devel下setup.bash的理解

在创建了ros的工作空间之后 在工作空间的devel文件夹中存在几个setup.*sh形式的环境变量设置脚本 使用source命令运行这些脚本文件&#xff0c;则工作空间的环境变量设置可以生效&#xff08;如可以找到该工作空间内的项目&#xff09;。 source devel/setup.bash 设置环境变量…

# Go学习-Day6

文章目录 Go学习-Day6封装继承接口 Go学习-Day6 个人博客&#xff1a;CSDN博客 封装 类似java的类的封装&#xff0c;这里我们利用大小写和工厂模式来实现封装的功能略过 继承 相似的类具有相似的方法&#xff0c;反复绑定相同的方法&#xff0c;代码冗余&#xff0c;所以引…

Zipkin开源的分布式链路追踪系统

Zipkin是一款开源的分布式链路追踪系统,主要功能包括: 1. 采集跟踪数据 - Zipkin client库负责收集并上报各服务的请求信息。 2. 存储跟踪数据 - 存储层默认采用Zipkin自带的基于内存的快速存储,也支持整合MySQL、Cassandra等外部存储。 3. 查询接口 - 提供RESTful API进行跟…

Vue全局后置守卫

全局后置守卫 一、在 router 目录下的 index.js 文件中配置全局后置守卫。 import Vue from vue import VueRouter from vue-router Vue.use(VueRouter)import Home from ../views/Home.vue import About from ../views/About.vue import Login from ../views/Login.vueconst…

Ubuntu 22.04.3 LTS 维护更新发布

导读近日消息&#xff0c;Canonical 今天发布了代号为 Jammy Jellyfish、长期支持的 Ubuntu 22.04 第 3 个维护版本更新&#xff0c;距离上个版本相隔 6 周时间。 Ubuntu 22.04.3 LTS 最大的亮点在于内核升级到 Linux Kernel 6.2&#xff0c;此外 Mesa 图形堆栈也升级到 23.0.…

qt 实现音视频的分贝检测系统

项目场景&#xff1a; 目前的产品经常播放m3u8流&#xff0c;有的视频声音正常&#xff0c;有的视频声音就偏低&#xff0c;即使放到最大音量声音也是比较小&#xff0c;所以就产生了某种需求&#xff0c;能否自动感知视频声音的大小&#xff0c;如果发现声音比较小的情况&…

C++头文件和std命名空间

C 是在C语言的基础上开发的&#xff0c;早期的 C 还不完善&#xff0c;不支持命名空间&#xff0c;没有自己的编译器&#xff0c;而是将 C 代码翻译成C代码&#xff0c;再通过C编译器完成编译。 这个时候的 C 仍然在使用C语言的库&#xff0c;stdio.h、stdlib.h、string.h 等头…

FFmpeg<第一篇>:环境配置

1、官网地址 http://ffmpeg.org/download.html2、linux下载ffmpeg 下载&#xff1a; wget https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2解压&#xff1a; tar xvf ffmpeg-snapshot.tar.bz23、FFmpeg ./configure编译参数汇总 解压 ffmpeg-snapshot.tar.bz2 之后&…

【附安装包】Python-3.9.5安装教程

软件下载 软件&#xff1a;Python版本&#xff1a;3.9.5语言&#xff1a;英文大小&#xff1a;26.9M安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.5GHz 内存2G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a;https://pan.baidu.com/…