一、用模板实现单例模式

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

为了实现线程安全,需要在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++编程规范

转载于:https://www.cnblogs.com/alantu2018/p/8471404.html

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

  1. C++11线程库模板

    推荐一个非常好的C++11的线程库模板:https://github.com/progschj/ThreadPool/blob/master/ThreadPool.h 包含了C++11的特性,重点学习 ...

  2. 走进AngularJs(二) ng模板中常用指令的使用方式

    通过使用模板,我们可以把model和controller中的数据组装起来呈现给浏览器,还可以通过数据绑定,实时更新视图,让我们的页面变成动态的.ng的模板真是让我爱不释手.学习ng道路还很漫长,从模板 ...

  3. 项目案例模板之jdbc两种连接方式

    项目案例模板之jdbc两种连接方式 第一种连接方式 JDBCUtils.java package jdbc;​import org.junit.jupiter.api.Test;​import jav ...

  4. Java实现根据Word模板填充表格数据(poi方式),以及doc和docx转PDF,最全最详细版本,解决外部引用jar在linux上报ClassNotFound的问题。

    Java实现根据Word模板填充表格数据(poi方式),以及doc和docx转PDF,最全最详细版本,解决外部引用jar在linux上报ClassNotFound的问题. 适用场景: 1.固定格式的W ...

  5. poi模板操作word两种实现方式

    目录 1.手动创建模板 1.1 jar包导入 1.2 Excel工具编写 1.3 创建模板 1.4 调用模板生成接口 1.5 重写 WordExportUtil.exportWord07(templa ...

  6. 模板代码复用的三种方式: 宏, 继承, 包含

    模板代码复用 在模板中,可能会遇到以下情况: 多个模板具有完全相同的顶部和底部内容 多个模板中具有相同的模板代码内容,但是内容中部分值不一样 多个模板中具有完全相同的 html 代码块内容 宏 对宏( ...

  7. html pdf 模板,记一次 HTML 模板 转 PDF

    HTM模板的样式和实际转pdf样式会有非常大的差距 获取模板的方式也是十分曲折... 这里记录一下便捷的方式 第一步: 在前端调用windows的打印页面 这里的样式完全和html一一致:左侧 目标打 ...

  8. php模板引擎如何实现,php模板引擎技术简单实现

    用了smarty,tp过后,也想了解了解其模板技术是怎么实现,于是写一个简单的模板类,大致就是读取模板文件->替换模板文件的内容->保存或者静态化 tpl.class.php主要解析 as ...

  9. 提高开发效率之安卓模板(上面有四种模板的教程,我之前会两种,看完之后还是只会两种2333)

    原文地址: juejin.im/post/5c7339- 在平时的开发工作中,我们经常将一个地方的代码,复制粘贴到另外一个地方,俗称搬砖,搬砖搬多了,作为一个资深的挨踢民工,难免会总结一些提高生产力的 ...

最新文章

  1. 【视频】【zt】温馨的求婚
  2. docker命令大全
  3. Why Spring Boot
  4. 终极解码播放mkv声音小的解决
  5. 手机充满电不拔有什么影响吗?
  6. Android Multimedia框架总结(九)Stagefright框架之数据处理及到OMXCodec过程
  7. @@HOW TO:检查 MDAC 版本
  8. “易升”升级Win10卡在99%的处理办法
  9. 收藏+下载!Flink 社区 2021 最新最全学习渠道汇总
  10. pcl小知识(十二)—— 斯坦福兔子和其他图形学模型数据下载
  11. Linux中的Cat命令–如何使用Cat或Touch创建文本文件
  12. 南昌大学计算机学硕和专硕,专硕和学硕哪个好?该怎么选?
  13. 老马 Markov 其人
  14. 聊聊程序员与英语,程序员不学英语行吗?
  15. 从零开始入门 K8s | Kubernetes API 编程利器:Operator 和 Operat
  16. 关于腾讯云服务器的域名备案流程(尽力图文并茂)
  17. 李宏毅HW01——新冠疫情数据的预测
  18. 吴裕雄--天生自然 诗经:游子吟
  19. 深度神经网络的理解和实践例子,很好。
  20. 蓝牙之二十-设备类型

热门文章

  1. python的flask框架显示柱状图_使用Python的Flask框架,结合Highchart,动态渲染图表(Ajax 请求数据接口)...
  2. js 多个定时器_从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理(二)
  3. mingle_大众汽车品牌SUV之夜,数千平米的mingle区和超长弧面屏了解一下?
  4. Redis初学17:集群
  5. 【蓝桥java】递归基础之39级台阶
  6. 小程序云开发,判断数据库表的两个字段匹配 云开发数据库匹配之 and 和 or 的配合使用
  7. dispatch callback ant design pro 网络请求回调函数
  8. 083、Prometheus架构(2019-05-05 周日)
  9. 大数据推荐(个性化推荐)
  10. C#图片灰度处理(位深度24→位深度8),用灰度数组byte[]新建一个8位灰度图像Bitmap 。...