用模板实现单例模式(线程安全)、模板方式实现动态创建对象
一、用模板实现单例模式
在前面的文章中,用过多种方法实现单例模式,现在用模板方式来实现:
为了实现线程安全,需要在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\n", 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++编程规范