• 用模板实现单例模式(线程安全)、模板方式实现动态创建对象


    一、用模板实现单例模式

    前面的文章中,用过多种方法实现单例模式,现在用模板方式来实现:

    为了实现线程安全,需要在linux 下使用pthread_mutex_t 加锁,请使用g++ 编译并需要链接 -lpthread

    使用的是double-check lock, 指针instance_ 最好声明为volatile,防止优化。

    Singleton.h:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
    /*************************************************************************
        > File Name: Singleton.h
        > Author: Simba
        > Mail: dameng34@163.com
        > Created Time: Wed 02 Apr 2014 01:33:39 AM PDT
     ************************************************************************/

    #ifndef _SINGLETON_H_
    #define _SINGLETON_H_

    #include <iostream>
    #include <stdlib.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>

    using namespace std;

    template < typename T > class Singleton
    {

    public:
        static T &GetInstance()
        {
            Init();
            return *instance_;
        }

    private:
        static void Init()
        {
            if (instance_ == 0)
            {

                pthread_mutex_lock(&g_mutex);
                if (instance_ == 0)
                {
                    instance_ = new T;
                    atexit(Destroy);    //程序结束时调用注册的函数
                }
                pthread_mutex_unlock(&g_mutex);
            }
        }

        static void Destroy()
        {
            delete instance_;
        }

        Singleton(const Singleton &other);
        Singleton &operator=(const Singleton &other);
        Singleton();
        ~Singleton();

        static T * volatile instance_;
        static pthread_mutex_t g_mutex;
    };

    template < typename T >
    T * volatile Singleton < T >::instance_ = 0;

    template < typename T >
    pthread_mutex_t Singleton<T> ::g_mutex = PTHREAD_MUTEX_INITIALIZER;

    #endif              // _SINGLETON_H_

    main.cpp:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
    /*************************************************************************
        > File Name: main.cpp
        > Author: Simba
        > Mail: dameng34@163.com
        > Created Time: Wed 02 Apr 2014 01:30:13 AM PDT
     ************************************************************************/

    #include "Singleton.h"

    class ApplicationImpl
    {

    public:
        ApplicationImpl()
        {
            cout << "ApplicationImpl ..." << endl;
        }

        ~ApplicationImpl()
        {
            cout << "~ApplicationImpl ..." << endl;
        }

        void Run()
        {
            cout << "Run ..." << endl;
        }
    };

    typedef Singleton < ApplicationImpl > Application;

    void *routine(void *arg)
    {
        Application::GetInstance().Run();
    }

    int main(void)
    {
        Application::GetInstance().Run();

        pthread_t tid;
        int ret;
        if ((ret = pthread_create(&tid, NULL, routine, NULL)) != 0)
        {
            fprintf(stderr, "pthread create: %s ", strerror(ret));
            exit(EXIT_FAILURE);
        }

        Application::GetInstance().Run();

        pthread_join(tid, NULL);

        return 0;
    }


    即 将Singleton 实现为模板类,将ApplicationImpl 类包装成单例模式类,可以看到构造函数和析构函数都只调用了一次。程序使用一个小技巧,用axexit 函数注册了程序结束时需要调用的函数。


    二、模板方式实现动态创建对象

    前面的文章曾经使用宏定义的方式实现动态创建对象,现在在 DynBase.h 中用模板类将宏定义替换掉,其他代码不变:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    //class Register
    //{
    //public:
    //    Register(const string &name, CREATE_FUNC func)
    //    {
    //        DynObjectFactory::Register(name, func);
    //    }
    //};
    //
    //#define REGISTER_CLASS(class_name) 
    //class class_name##Register { 
    //public: 
    //    static void* NewInstance() 
    //    { 
    //        return new class_name; 
    //    } 
    //private: 
    //    static Register reg_; 
    //}; 
    //Register class_name##Register::reg_(#class_name, class_name##Register::NewInstance)

    template <typename T>
    class DelegatingClass
    {
    public:
        DelegatingClass(const string &name)
        {
            DynObjectFactory::Register(name, &(DelegatingClass::NewInstance));
        }

        static void *NewInstance()
        {
            return new T;
        }
    };

    #define REGISTER_CLASS(class_name) DelegatingClass<class_name> class##class_name(#class_name)

    即 REGISTER_CLASS(class_name) 宏定义展开会构造一个模板类实例对象,调用3次宏定义即3个模板类实例对象,调用构造函数

    const string &name),进而调用Register 完成注册,接下去的流程与以前的程序一样,不再赘述。输出如下:

    参考:

    C++ primer 第四版
    Effective C++ 3rd
    C++编程规范

  • 相关阅读:
    最简单的非交互ssh远程执行命令expect脚本
    [转]解决Adobe Reader X中金山词霸不能取词故障
    《TCP/IP Sockets 编程》笔记1
    Visual Studio 2005中无法调试CLR C++的枚举类型
    查找字符串中字符间不同的最大子串
    《C++ Primer》关于自增自减操作符的描述错误
    LVM逻辑卷管理
    《TCP/IP Sockets 编程》笔记2
    《TCP/IP Sockets 编程》笔记7
    Linux文件
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8471404.html
Copyright © 2020-2023  润新知