C++中的单例类模板

本节课讲述单例类模式,提出在架构设计中某些类最多只能有一个对象的需求,探讨如何定义此类。介绍单例模式控制对象数目需隐藏构造函数,还指出其存在需重复定义静态成员变量和函数的问题,最后给出解决方案,即开发单例类模板供后续使用。

1,本节课讲述单例类模式,实现并抽取相关代码实现单例类模板,在以后开发工作 中,如果想要使用单例模式,那么直接使用今天开发的单例类模板就可以;

 

2,需求的提出:

    1,在架构设计时,某些类在整个系统生命期中最多只能有一个对象存在    ( Single Instance );

       1,如超市收银系统,由外观来说其由显示器、扫描枪、收款箱组成,这几部分都只有一个部件,用面向对象的思想来进行架构设计的话,扫描枪应该对应到代码里面的一个类,它应该用来创建对象,实际的硬件只有一个扫描枪,肯定要限制扫描枪对应的类只能创建一个对象;

       2,这个时候单例模式的需求就出来了;

   

3,问题:

    1,如何定义一个类,使得这个类最多只能创建一个对象?

   

4,单例模式:

    1,要控制类的对象数目,必须对外隐藏构造函数;

       1,要创建一个对象,必然要调用构造函数,因此可以控制构造函数的访问属性;

    2,思路:

       1,将构造函数的访问属性设置为 private;

           1,外界就不能创建对象了;

       2,定义 instance 并初始化为 NULL;

       3,当需要使用对象时,访问 instance 的值;

           1,空值:创建对象,并用 instance 标记;

           2,非空值:返回 instance 标记的对象;

          

5,单例模式初探编程实验:

#include <iostream>
#include <string>

using namespace std;

class SObject
{
    static SObject* c_instance;  // 定义标识符指针;

    /* 不需用拷贝和赋值 */    
    SObject(const SObject&);
    SObject& operator= (const SObject&);
    
    SObject()  // 构造函数创建为私有的;
    {
    }
public:
    static SObject* GetInstance();
    
    void print()
    {
        cout << "this = " << this << endl;
    }
};

SObject* SObject::c_instance = NULL; //类的外部对静态变量定义并初始化;

SObject* SObject::GetInstance()  // 创建对象
{
    if( c_instance == NULL )
    {
        c_instance = new SObject();
    }
    
    return c_instance;
}

int main()
{
    SObject* s = SObject::GetInstance();
    SObject* s1 = SObject::GetInstance();
    SObject* s2 = SObject::GetInstance();
    
    s->print();  // this = 0x940a008
    s1->print();  // this = 0x940a008
    s2->print();  // this = 0x940a008
    
    return 0;
}

    1,上述代码中并没有释放这个唯一的对象,这是因为单例模式所对应的对象在系统的生命周期中都是存在的,如果这个系统还在运行,就不需用释放它;

    2,单例模式所得到的对象在整个系统运行过程中是绝对不释放的;

   

6,单例模式存在问题(这里做的是锦上添花的事,要求完美):

    1,需要使用单例模式时:

       1,必须定义静态成员变量 c_instance;

       2,必须定义静态成员函数 GetInstance();

    2,如果现在要开发超市收银系统,那么开发扫描枪对应的类需要用单例模式来实现,收款箱对应的类也要用单例模式来实现,这个时候就要写重复的静态成员变量和静态成员函数;

    3,静态成员变量和静态成员函数和我们类的实际功能没有关系,这是单例模式的逻辑;

      

7,解决方案:

    1,将单例模式相关的代码抽取出来,开发单例类模板,当需要单例类时,直接使用单例类模板;

   

8,单例类模板编程实验:

    1,单例模式类模板 Singleton.h 文件:

 1 #ifndef _SINGLETON_H_
 2 #define _SINGLETON_H_
 3 
 4 template
 5 < typename T >
 6 class Singleton
 7 {
 8     static T* c_instance;
 9 public:
10     static T* GetInstance();
11 };
12 
13 template
14 < typename T >
15 T* Singleton<T>::c_instance = NULL;
16 
17 template
18 < typename T >
19 T* Singleton<T>::GetInstance()
20 {
21     if( c_instance == NULL )
22     {
23         c_instance = new T();
24     }
25     
26     return c_instance;
27 }
28 
29 #endif

    2,单例模式的使用:

 1 #include <iostream>
 2 #include <string>
 3 #include "Singleton.h"
 4 
 5 using namespace std;
 6 
 7 class SObject
 8 {
 9     friend class Singleton<SObject>;    // 当前类需要使用单例模式
10     
11     SObject(const SObject&);
12     SObject& operator= (const SObject&);
13     
14     SObject()
15     {
16     }
17 public:
18     
19     void print()
20     {
21         cout << "this = " << this << endl;
22     }
23 };
24 
25 int main()
26 {
27     SObject* s = Singleton<SObject>::GetInstance();
28     SObject* s1 = Singleton<SObject>::GetInstance();
29     SObject* s2 = Singleton<SObject>::GetInstance();
30     
31     s->print();  // 0x9621008;
32     s1->print();  // 0x9621008;
33     s2->print();  // 0x9621008;
34     
35     return 0;
36 }

    3,使用单例类模板方法:

       1,构建对象的函数全部私有化;

       2,声明单例类模板为此类的友元(可以访问这个类);

    4,此单例类模板在我们今后开发工作中都可以使用;

   

9,小结:

    1,单例模式是开发中最常用的设计模式之一;

    2,单例模式的应用使得一个类最多只有一个对象;

    3,可以将单例模式相关的代码抽象成类模板;

    4,需要使用单例模式的类直接使用单例类模板;

转载于:https://www.cnblogs.com/dishengAndziyu/p/10919214.html

<think>我们在处理用户关于C++模式模板类实现示的查询根据用户提供的信息,我们可以直接给出示代码并解释我们也会参考站内引用提供的信息,特别是引用[3]和引用[5]中关于模式模板的实现另外,引用[2]中提到了使用可变参数模板优化模式,我们也可以考虑展示设计思路:1.模式的核心:确保一个类只有一个实,并提供一个全局访问点。2.需要禁用拷贝构造、移动构造、赋值运算符等,防止创建多个实。3.使用静态局部变量(C++11以后保证线程安全)来创建唯一实。4.考虑使用模板使得模式可以复用。我们参考引用[3]和引用[5]的代码,结合可变参数模板(引用[2]中提到)来展示一个更通用的模板。注意:在C++11及以后,静态局部变量的初始化是线程安全的,因此可以用这种方式实现线程安全的。我们将实现两个版本:版本1:基本模板(不支持构造参数)版本2:使用可变参数模板支持构造参数(引用[2]中提到)但注意引用[3]中使用了delete来禁用拷贝等操作,我们也会采用。然而,用户可能需要一个完整的示,因此我们将提供代码示和解释。另外,根据引用[4],我们需要解释为什么使用模式以及注意事项。由于用户要求实现模板类,我们重点在模板上。我们按照如下步骤:1.实现一个基本的模板类(不支持构造参数)2.实现一个支持可变参数的模板类(支持在创建实时传递参数)3.给出使用示注意:在模板中,我们通常将构造函数设为私有,但是模板类需要能够创建模板参数T的实,因此我们需要将模板声明为T的友元?或者将T的构造函数公开?但这样可能会允许外部创建实。解决方案:在模板中,我们将模板类声明为T的友元(如引用[2]中所示),这样模板就可以访问T的私有构造函数。但这样对每个T都需要在类内声明友元,不太方便。另一种方法是要求T的构造函数是公有的,然后我们在模板中控制创建的唯一性(因为通过模板的接口获取实,而外部不能直接创建T的实?但实际上如果T的构造函数是公有的,外部还是可以创建实)。因此,正确的方法是在T中将模板类声明为友元,并私有化T的构造函数(包括拷贝构造等)。这样只有模板能创建T的实。所以,我们在使用模板时,需要让我们的目标类(比如A)将模板类声明为友元,并且将构造函数私有化。我们这里为了模板的通用性,在模板设计时并不直接处理友元,而是要求使用此模板的类必须将模板类声明为友元(如引用[2]所示)并私有化构造函数。接下来我们写代码:</think> ### C++ 模式模板类实现 #### 基本实现原理 模式通过以下机制确保类只有一个实: 1. 私有化构造函数和析构函数,防止外部实化 2. 禁用拷贝构造、移动构造和赋值运算符 3. 提供静态访问点返回唯一实 4. 利用 C++11 静态局部变量特性保证线程安全 [^1][^3] #### 模板类实现示 ```cpp template <typename T> class Singleton { public: // 删除拷贝和移动操作 Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; Singleton(Singleton&&) = delete; Singleton& operator=(Singleton&&) = delete; // 获取全局唯一实 static T& GetInstance() { static T instance; return instance; } protected: // 允许子类继承构造/析构 Singleton() = default; ~Singleton() = default; }; ``` #### 使用示 ```cpp class DatabaseConnection : public Singleton<DatabaseConnection> { friend class Singleton<DatabaseConnection>; // 声明友元 public: void Connect() { /* 连接实现 */ } void Query(const std::string& sql) { /* 查询实现 */ } private: // 私有化构造函数 DatabaseConnection() { std::cout << "DB connection established\n"; } }; int main() { // 获取唯一实 auto& db = DatabaseConnection::GetInstance(); db.Connect(); db.Query("SELECT * FROM users"); } ``` **输出**: ``` DB connection established Query executed: SELECT * FROM users ``` #### 关键设计点 1. **线程安全**:C++11 保证静态局部变量初始化线程安全 [^3] 2. **资源管理**:实在程序结束时自动销毁 3. **扩展性**: ```cpp // 支持构造参数的可变参数版本 template <typename T, typename... Args> T& GetInstance(Args&&... args) { static T instance(std::forward<Args>(args)...); return instance; } ``` 4. **继承约束**:派生类必须声明模板类为友元并私有化构造函数 [^5] #### 应用场景 1. 全局配置管理 2. 数据库连接池 3. 日志系统 4. 硬件设备访问接口 [^4] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值