当前位置: 首页 > news >正文

C++中的单例模式的实现

1 什么是单例模式

单例模式 是一种创建型设计模式,确保一个类在整个程序生命周期中只有一个实例,并提供一个全局访问点。

核心要求:

  1. 类不能被外部随意创建(禁止 public 构造函数或限制实例数量)。
  2. 不能被复制或移动。
  3. 提供一个全局访问接口(如 getInstance())。
  4. 实例的生命周期通常伴随整个程序。

2 模版单例的实现

2.1 单例模版GSingleton<T>

  • 使用场景:项目中需要大量单例,且希望统一管理时,使用单例模版会提高代码复用。单例模版类本身不能直接使用,而是作为基类被继承。需要实现单例的类只需要继承GSingleton即可。

  • 注意:模版基类GSingleton的构造函数和析构函数必须是protected修饰,不能用private,因为派生类在构造时或者析构时可以调用。而派生类T的构造函数和析构函数可以由private修饰。

template<typename T>
class GSingleton
{
protected:GSingleton() = default;~GSingleton() = default;  // 非虚,除非你真的需要// 禁止拷贝和移动GSingleton(const GSingleton&) = delete;GSingleton& operator=(const GSingleton&) = delete;GSingleton(GSingleton&&) = delete;GSingleton& operator=(GSingleton&&) = delete;public:static T& getInstance() {static T instance;return instance;}
};
  • 模版类详细介绍
  1. protect:修饰的方法或者成员变量只能被本类、派生类以及友元访问。
  2. Gsingleton<T>是基类,必须是protected,这样派生类在构造时才可以调用父类的构造函数。
  3. GSingleton = default:表示显式要求编译器生成一个默认构造函数(无参构造函数)
  4. ~GSingleton() = default:表示让编译器生成默认析构函数。
  5. GSingleton(const GSingleton&) = delete:这是对拷贝构造函数的声明,禁止拷贝。
    const GSingleton&:表示对另一个GSingleton对象的常量引用。
    delete表示这个函数被显示删除,不能使用。
    Access a;
    Access b(a);        // ❌ 错误!调用拷贝构造函数
    Access c = a;       // ❌ 错误!也是拷贝构造(赋值语法,实际是构造)
    
  6. GSingleton& operator=(const GSingleton&) = delete:这是对拷贝赋值运算符的声明,禁止拷贝。
    operator=:表示赋值操作符的重载。
    Access a;
    Access b;
    b = a;              // ❌ 错误!调用拷贝赋值
  7. GSingleton(GSingleton&&) = delete:这是移动构造函数的声明,禁止移动构造。
    GSingleton&&:是一个右值引用,表示临时对象或者可移动的对象。
    移动不是拷贝,而是资源转移,将一个临时对象所拥有的资源转移给另一个对象,而原对象不再拥有该资源。
    移动避免了不必要的内存分配和数据赋值,因此非常高效。
    Access a;
    Access b(std::move(a));  // ❌ 错误!试图移动构造(即使 NRVO 优化,语义上也不允许)
  8. GSingleton& operator=(GSingleton&&) = delete:这是移动赋值运算符,禁止将一个临时对象移动赋值给已有对象。
    Access a;
    Access b;
    b = std::move(a);   // ❌ 错误!禁止移动赋值

✅ 总结

代码禁止的操作
Access(const Access&) = delete;Access b(a); 或 Access b = a;
Access& operator=(const Access&) = delete;b = a;
Access(Access&&) = delete;Access b(std::move(a));
Access& operator=(Access&&) = delete;b = std::move(a);

2.2 使用单例模版定义派生类

class GLoggerImpl : public GSingleton<GLoggerImpl>
{
private:GLoggerImpl();friend class GSingleton<GLoggerImpl>;
public:~GLoggerImpl();void WriteLog(int logLevel, const char* file, int line, const char* function, const char* format, va_list args);
}

注意:在声明GloggerImpl的类时使用了friend class GSingleton<GLoggerImpl>,表示声明让模版类成为友元。

原因:在调用GLoggerImpl::getInstance()时,

// template<typename T> class GSingleton 
static T& getInstance() {static T instance;  // ← 这里要构造 T,即 GLoggerImplreturn instance;
}

static T instance会调用GLoggerImpl的构造函数,由于GLoggerImpl()是private或者protected,而GSingleton<GLoggerImpl>模版类不是GLoggerImpl类的成员变量,默认无法访问GLoggerImpl的构造函数,因此要声明friend来显示授权。

友元:是C++的一个关键字,它允许一个类、函数或者模版访问另一个类的private和protected成员,即使它不是那个类的成员函数或者派生类。

  • friend可以修饰函数,称为友元函数,可以在一个类中声明友元函数,这样该函数可以访问该类的私有成员变量或者成员函数。
  • friend可以修饰类,成为友元类,可以访问所在类中的private或者protect的成员,友元关系是单向的。
  • friend可以修饰一个模版类或者模版函数,成为友元模版。例如GloggerImpl中friend修饰的模版。

2.3 单例类的使用

由于GLoggerImpl继承了GSingleton的模版基类,因此继承了父类静态的getInstance()方法。所以通过GLoggerImpl::getInstance()可以获取该类唯一的单例对象。

void LogD(const char* file, int line, const char* function, const char* format, ...) {va_list args;va_start(args, format);GLoggerImpl::getInstance()->WriteLog(LEVEL_DEBUG, file, line, function, format, args);va_end(args);
}

3 单例类的实现

class Singleton {
public:static Singleton& getInstance() {static Singleton instance;  // C++11 起,线程安全return instance;}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;Singleton(Singleton&&) = delete;Singleton& operator=(Singleton&&) = delete;private:Singleton() = default;~Singleton() = default;
};

 

 


文章转载自:

http://R7Z6Snpq.wmmtL.cn
http://gIFpxpAm.wmmtL.cn
http://8RzqvhpK.wmmtL.cn
http://7v9qyGlm.wmmtL.cn
http://BUIDV0R8.wmmtL.cn
http://VOt3WU01.wmmtL.cn
http://YxQpBkEH.wmmtL.cn
http://KA6tOJ9q.wmmtL.cn
http://tO8td7Xv.wmmtL.cn
http://IhxIabeP.wmmtL.cn
http://KIJ3QWtM.wmmtL.cn
http://i6AifroR.wmmtL.cn
http://kOL7xyLv.wmmtL.cn
http://9oKQ5dod.wmmtL.cn
http://nUBgcmtu.wmmtL.cn
http://Nu5IcSTH.wmmtL.cn
http://Lfmi09sW.wmmtL.cn
http://cQUr3RhU.wmmtL.cn
http://4uspw0CN.wmmtL.cn
http://ZXcYSnF4.wmmtL.cn
http://VXx9BmSl.wmmtL.cn
http://hHUwWqzQ.wmmtL.cn
http://WHqZzYxx.wmmtL.cn
http://tJX4nZtp.wmmtL.cn
http://5n85zIiJ.wmmtL.cn
http://8OwJtQZ6.wmmtL.cn
http://iDPUv4nl.wmmtL.cn
http://NZOqAJXo.wmmtL.cn
http://pb6dX9JD.wmmtL.cn
http://27FpVLQY.wmmtL.cn
http://www.dtcms.com/a/376946.html

相关文章:

  • 淘宝闪购基于FlinkPaimon的Lakehouse生产实践:从实时数仓到湖仓一体化的演进之路
  • 云手机怎样进行自动化运行?
  • FPGA入门-状态机
  • 【Python Tkinter 】图形用户界面(GUI)开发及打包EXE指南
  • 工作效率翻倍!Excel多文件合并工具
  • 【Pywinauto库】8.4 pywinauto.timings模块
  • 4.7 静态分支, 动态分支和变体
  • LangGraph中ReAct模式的深度解析:推理与行动的完美融合——从理论到实践的智能Agent构建指南
  • 【机械故障】使用fir滤波器实现数据拟合
  • vue3 中 npm install mammoth 与 npm install --save mammoth 的主要区别说明
  • Milvus基于docker主机外挂实践
  • 从零搭建企业级日志系统:Web + App 全端解决方案实战!
  • 【算法--链表】138.随机链表的复制--通俗讲解
  • Nodejs(③Stream)
  • iOS 26支持的设备列表
  • 日记 - 2025.9.10 读研日记(一)
  • 【JVM】故障诊断和性能监控命令
  • Java大厂面试实录:在线教育场景下微服务架构与智能推荐实践(含技术详解)
  • 实战:HarmonyOS 中 HEIF 图像开发全流程(转码篇 兼容场景)
  • 融智学生活方式DBA 小生境融智:身心健康就是美,抓住刚需就是赢
  • 【高级】系统架构师 | 2025年上半年综合真题DAY3
  • CentOS 7部署Zabbix5.0
  • [rStar] 策略与奖励大语言模型
  • 使用命令centos把普通用户设置为管理员
  • 机器学习实操项目03——Scikit-learn介绍及简单分类案例
  • 了解网站安全监测系统的重要性
  • 图像尺寸和CMOS的关联
  • 视频转webp批量处理工具哪个好?这里有答案
  • cuda-NCCL笔记(3)-- 分布式训练LeNet
  • Android Studio开发环境配置