单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点,其类图如下图所示: 基于C  11实现的单例模式 - 图1在《设计模式 可服用面向对象软件的基础》一书中给出过C++中实现单例模式的经典实现,但书中给出的实现有着下面的不足:

  • 未使用模版技术,无法将单例模式类与具体类分离,从而无法方便的将任何类设置为单例类
  • 未使用智能指针技术,需要手动释放内存

而本文的代码的实现中则通过C++11的以下机制克服了上面的缺点:

  • 使用可变参数模版技术,使得单例模式支持任意参数的构造函数
  • 使用类模板技术,支持以非继承的方式将任意类转为“单例类”
  • 使用智能指针技术,无需担心单例对象内存的释放
  • 也支持通过继承的方式,使得子类为单例类

    下面代码的实现参考《深入应用C++11 代码优化与工程级应用》

  1. //
  2. // MySingleton.h
  3. // Created by Yyh on 2022/3/13.
  4. #ifndef _MySingleton_h_
  5. #define _MySingleton_h_
  6. #include <memory>
  7. template <typename T>
  8. class MySingleton
  9. {
  10. public:
  11. //初始化单例
  12. template<typename ... Args>
  13. static std::shared_ptr<T> Instance(Args &&... args)
  14. {
  15. m_pInstance = std::make_shared<T>(std::forward<Args>(args)...); //完美转发
  16. return m_pInstance;
  17. }
  18. //获取单例
  19. static std::shared_ptr<T> GetInstance()
  20. {
  21. if(m_pInstance == nullptr)
  22. {
  23. //如果未初始化的前提下获取单例则抛出异常
  24. throw std::logic_error("the instance is not init, please initialize the instance first");
  25. }
  26. return m_pInstance;
  27. }
  28. protected:
  29. virtual ~MySingleton(){}
  30. MySingleton(){}
  31. private:
  32. static std::shared_ptr<T> m_pInstance;
  33. };
  34. template <class T>
  35. std::shared_ptr<T> MySingleton<T>::m_pInstance = nullptr;
  36. #endif

下面是测试函数:

  1. #include <iostream>
  2. #include "MySingleton.h"
  3. using namespace std;
  4. struct A
  5. {
  6. A()
  7. {
  8. strText = "A()";
  9. }
  10. std::string strText;
  11. };
  12. struct B
  13. {
  14. B(std::string strParam)
  15. {
  16. strText = std::string("B(") + strParam + ")";
  17. }
  18. std::string strText;
  19. };
  20. struct C : public MySingleton<C>
  21. {
  22. std::string strText;
  23. C(std::string strParam)
  24. {
  25. strText = std::string("C(") + strParam + ")";
  26. }
  27. };
  28. int main(int argc, char *argv[]) {
  29. MySingleton<A>::Instance();
  30. MySingleton<B>::Instance("b");
  31. C::Instance("c");
  32. cout << "A:" << MySingleton<A>::GetInstance()->strText << endl;
  33. cout << "B:" << MySingleton<B>::GetInstance()->strText << endl;
  34. cout << "C:" << C::GetInstance()->strText << endl;
  35. }

效果图如下:
image.png

参考:

  • 《深入应用C++11 代码优化与工程级应用》
  • 《设计模式 可服用面向对象软件的基础》