从零开始学C++之模板(四):用模板实现单例模式(线程安全)、模板方式实现动态创建对象

一、用模板实现单例模式

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

为了实现线程安全,需要在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: [email protected]
    > 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: [email protected]
    > 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\n", strerror(ret));
        exit(EXIT_FAILURE);
    }

    Application::GetInstance().Run();

    pthread_join(tid,  NULL);

     return  0;
}


从零开始学C++之模板(四):用模板实现单例模式(线程安全)、模板方式实现动态创建对象_第1张图片


即 将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个模板类实例对象,调用构造函数

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


从零开始学C++之模板(四):用模板实现单例模式(线程安全)、模板方式实现动态创建对象_第2张图片


参考:

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



你可能感兴趣的:(用模板实现单例模式,模板方式实现动态创建对象)