C++ - Singleton单例模式

时间:2022-08-11 20:50:57

C++ - Singleton单例模式

//【实现单例步骤】
// 1.构造函数私有化
// 2.增加静态的、私有的当前类的指针变量
// 3.提供一个静态的公有接口,可让用户获得单例对象

 1 #include<iostream>
 2 
 3 using namespace std;
 4 
 5 class A
 6 {
 7 private: // 步骤1  8     A() {};
 9 public:
10     static A* getInstance() //步骤3 11     {
12         return a;
13     }
14 private:
15     static A* a; // 步骤2 16 };
17 
18 A* A::a = nullptr;
19 //【实现单例步骤】
20 // 1.构造函数私有化
21 // 2.增加静态的、私有的当前类的指针变量
22 // 3.提供一个静态的公有接口,可让用户获得单例对象
23 
24 //单例:懒汉式 、恶汉式
25 // <1> 懒汉式
26 class Singleton_lazy 
27 {
28 private:
29     Singleton_lazy() { cout << "创建 Singleton_lazy " << endl; };
30 public:
31     static Singleton_lazy* getInstance()
32     {
33         if (pSingleton_lazy == nullptr) // 如果单例对象没被创建(如果创建了,那就跳过呗)
34         {
35             pSingleton_lazy = new Singleton_lazy; // 那就TM建一个
36         }
37         return pSingleton_lazy;
38     }
39 private:
40     static Singleton_lazy* pSingleton_lazy;
41 };
42 Singleton_lazy* Singleton_lazy::pSingleton_lazy = nullptr;
43 
44 // <2> 饿汉式
45 class Singleton_hungry
46 {
47 private:
48     Singleton_hungry() { cout << "创建 Singleton_hungry " << endl; };
49 public:
50     static Singleton_hungry* getInstance()
51     {
52         return pSingleton_hungry;
53     }
54 private:
55     static Singleton_hungry* pSingleton_hungry;
56 };
57 Singleton_hungry* Singleton_hungry::pSingleton_hungry = new Singleton_hungry;//直接在类外创建单例对象
58 
59 
60 int main()
61 {
62     //A::getInstance();
63     cout << "main开始的地方" << endl;
64     Singleton_lazy::getInstance();
65     Singleton_hungry::getInstance();
66 }

C++ - Singleton单例模式

可以看到,恶汉模式在main执行之前已经初始化好了。

 举例子:SLAM中我们需要在多个文件中读取参数文件,所以,这里必须把Config写成 Singleton。它只有一个全局对象,当我们设置参数文件时,创建该对象【整个程序之创建一个对象】并读取参数文件,随后可以在任意位置读取该文件中的参数值。

 1 class Config
 2 {
 3 private:
 4     // <1> 步骤1:构造函数私有化
 5     Config(){};
 6     cv::FileStorage file_;
 7 public:
 8     ~Config();
 9     // <3> 步骤3:提供静态的、公有的接口;可让用户获取单例
10     static void setParameterFile(const std::string& filename); // 类似于 static void getInstance()
11 
12     template<typename T>
13     static T get(const std::string& key)
14     {
15         return T(Config::config_->file_[key]);
16     }
17     
18 private:
19     // <2> 步骤2:增加静态的、私有的当前类的指针
20     static std::shared_ptr<Config> config_;
21 };
22 
23 std::shared_ptr<Config> Config::config_ = nullptr;
24 
25 void Config::setParameterFile(const std::string & filename)
26 {
27     if (config_ == nullptr) 
28     {
29         config_ = std::shared_ptr<Config>(new Config);
30     }
31     config_->file_ = cv::FileStorage(filename.c_str(), cv::FileStorage::READ);
32     // 异常处理
33     if (config_->file_.isOpened() == false)
34     {
35         std::cerr << "parameter file " << filename << "do not exsit" << std::endl;
36         config_->file_.release();
37         return;
38     }
39 }
40 
41 Config::~Config()
42 {
43     if (file_.isOpened())
44     {
45         file_.release();
46     }    
47 }

显然这里是懒汉模式,不过它新增了静态 模板类型的 get函数;

调用方式如下:

1 Config::setParameterFile("myparameter.yaml"); // 获取一个单例对象
2 double distance = Config::get<double>("distance");//通过静态成员函数获取参数,static能去掉?

不能去掉,原因:与普通的成员函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针.从这个意义上来说,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,只能调用其他的静态成员函数.

 

 

 

 

 

//将上述两个模式中的指针改为 共享指针

 1 #include<iostream>
 2 #include<memory>
 3 
 4 using namespace std;
 5 
 6 class Singleton_lazy
 7 {
 8 private:
 9     Singleton_lazy() { cout << "Singleton_lazy" << endl; };
10 public:
11     //static Singleton_lazy* GetInstance()
12     static shared_ptr<Singleton_lazy> GetInstance()
13     {
14         if (sp == nullptr)
15         {
16             //sp = new Singleton_lazy;
17             sp = shared_ptr<Singleton_lazy>(new Singleton_lazy);
18         }
19         return sp;
20     }
21 private:
22     //static  Singleton_lazy* sp;
23     static shared_ptr<Singleton_lazy> sp;
24 };
25 //Singleton_lazy* Singleton_lazy::sp = nullptr;
26 shared_ptr<Singleton_lazy> Singleton_lazy::sp = nullptr;
27 
28 class Singleton_hungry
29 {
30 private:
31     Singleton_hungry() { cout << "Singleton_hungry" << endl; };
32 public:
33     //static Singleton_hungry* GetInstance()
34     static void GetInstance()
35     {
36         //return sp;
37         return;
38     }
39 private:
40     //static Singleton_hungry* sp;
41     static shared_ptr<Singleton_hungry> sp;
42 };
43 shared_ptr<Singleton_hungry> Singleton_hungry::sp = shared_ptr<Singleton_hungry>(new Singleton_hungry);
44 
45 int main()
46 {
47     cout << "shiruiyu" << endl;
48     Singleton_lazy::GetInstance();
49     Singleton_hungry::GetInstance();
50     return 1;
51 }