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

news/2024/12/22 16:43:59/

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.ppmy.cn/news/1061173.html

相关文章

清洁能源使用的社会发展意义

应用清洁能源是转变经济增加途径的有效手段&#xff0c;能够在减少污染物、降低企业经营成本的同时&#xff0c;提高企业经济效益和社会经济效益。 应用清洁能源是保护环境的最佳方式和必然选择&#xff0c;改变末端治理的现状&#xff0c;采取以预防为主的环境保护与发展理…

在x86机器上的Docker运行arm64容器

1. 引言 工作中常用电脑主机CPU为x86架构&#xff0c;有时由于产品需要&#xff0c;我们需要编译aarch64架构的SDK或者应用程序供使用或者测试。 一种比较快捷的方式是使用aarch64的CPU构建相应操作系统&#xff0c;实现真机运行。但在无arm架构CPU环境下&#xff0c;我们可否…

Vue快速入门以及基础标签使用

目录 开始示例el挂载点data数据对象 vue基本标签v-textv-htmlv-on计数器示例实现v-showv-ifv-bind图片切换示例v-forv-on补充v-model axios网络请求axios基本使用vue中使用axios 开始示例 1.首先在html页面中引入vue的生产环境&#xff0c;在body标签中粘上下面代码 <scrip…

Nginx的HTTPS部署与安全性能优化

Nginx作为一款高性能的Web服务器和反向代理服务器&#xff0c;被广泛用于应用部署和负载均衡。在安全环保意识的逐渐提高下&#xff0c;HTTPS也成为现代Web应用中必不可少的一环。本篇文章将重点介绍Nginx的HTTPS部署和安全性能优化。 一、Nginx的HTTPS部署 证书申请 首先需要去…

机器学习基础10-审查回归算法(基于波士顿房价的数据集)

上一节介绍了如何审查分类算法&#xff0c;并介绍了六种不同的分类算法&#xff0c;还 用同一个数据集按照相同的方式对它们做了审查&#xff0c;本章将用相同的方式对回归算法进行审查。 在本节将学到&#xff1a; 如何审查机器学习的回归算法。如何审查四种线性分类算法。如…

# Go学习-Day6

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

图为科技_边缘计算在智能安防领域的作用

边缘计算在智能安防领域发挥着重要的作用。智能安防系统通常需要处理大量的图像、视频和传感器数据&#xff0c;并对其进行实时分析和处理。边缘计算可以将计算和数据处理功能移动到离数据源更接近的地方&#xff0c;例如摄像头、传感器设备或安防终端。 以下是边缘计算在智能…

基于云原生网关的流量防护实践

作者&#xff1a;涂鸦 背景 在分布式系统架构中&#xff0c;每个请求都会经过很多层处理&#xff0c;比如从入口网关再到 Web Server 再到服务之间的调用&#xff0c;再到服务访问缓存或 DB 等存储。在下图流量防护体系中&#xff0c;我们通常遵循流量漏斗原则进行流量防护。…