`
wx1569567608
  • 浏览: 60289 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

动态库中单例一记

 
阅读更多


20093729_7ubV.png

20093729_amtv.png



1       一个简单的Singleton

我们先来看一个简单的单件类的定义:

#include<iostream>

class Singleton

{

public:

static Singleton& GetSingleton()

{

    static Singleton singleton;

    return singleton;

}

void Print()

{

    std::cout<<"Singleton Print\n";

}

private:

Singleton::Singleton()

{

    std::cout<<"singleton constructor\n";

}

};

这个类提供了一些的功能(函数Print), 并禁止我们创建这个类的对象(构造函数为private), 提供给我们一个静态函数接口来访问这个单件对象(GetSingleton),利用静态变量的特点实现了其单一性。但是, 这个类有问题吗?

2       问题所在

是的,上面这个简单的类的确存在问题,而且是一个很严重的问题,这个问题让Singleton类完全失去它存在的意义, 因为它不再唯一!

是的, 当我们只在一个模块中使用这个类时(比如说,一个exe,这个类是没有问题的。但是, 一个稍微复杂一点的软件, 为了开发的便捷,提高复用度,降低耦合性等原因,其难免会被分成好几个模块。那么假设讲我现在有两个模块,一个DLL(singleton.dll), 用来提供一些基础的功能, 一个EXE(test.exe),用来提供真正的软件逻辑。 我现在singleton.dll中封装了一个Print的函数间(用类Singleton实现)并暴露出来。

singleton.dll

void Print()

{

    Singleton::GetSingleton().Print();

}

并在test.exe中这样调用:

Test.exe

Singleton::GetSingleton().Print();

Print();

这个时候,我们会发现在调用Singleton::GetSingleton().Print()时会产生一个Singleton对象, 而在调用Print()时, 也会产生一个Singleton对象, 也就是说我们有了两个Singleton实例, singleton不再是singleton。那么, 为什么会这样呢。

static Singleton& GetSingleton()

{

    static Singleton singleton;

    return singleton;

}

这个函数应该只会在第一次调用时创建Singleton对象,无论如何, 不应该出现会创建两次, 调用两次构造函数的情况。对于静态变量特性理解没错(只在第一次经过时被初始化), 编译器也没问题(vc8.0),难道两次经过该静态变量是都是第一次? 那么,难道两次调用的GetSingleton函数并不是同一个函数?让我们逐一来看:

1) Singleton::GetSingleton().Print()

Test.exe中直接调用该函数,因为包含的头文件singleton.h有完整的实现, 在链接时会在Test.exe保存一份Singleton::GetSingleton()的实现代码。

将其标为Singleton::GetSingleton_1();

2) Print();

Print()函数是从singleton.dll中导出而来的,而Print()会调用Singleton::GetSingleton(), 在链接模块singleton.dll时,因为其包含的头文件有完整的实现, 这个DLL也会保存一份Singleton::GetSingleton()的执行代码。 我将它标为Singleton::GetSingleton_2(), 虽然我们包含的是同一个头文件,两个是相同的函数名字, 但是这个函数在两个不同的模块中都存有一份独立的实现。实际上, 他们已经成为两个不同的函数了。

看来,两个函数的确不是同一个函数。

3       如何解决

既然知道了原因,就会有相应的解决方法。既然我们知道有两份独立的代码分别存在于两个模块中, 那么我们要做的就是让它只有一份。最好的结果就是这个函数保存在dll中, 在Test.exe不再存有该函数的执行代码, 而是调用dll中的那个函数。现在结果很明显了:将Singleton.h编译链接singleton.dll并将外部需要使用的函数暴露出来。这样, 不管有多少模块使用到singleton, 我们始终执行singleton.dll中的代码。

如下:

SINGLETON_API static Singleton& GetSingleton()

{

     static Singleton singleton;

     return singleton;

}

注:

#ifdef SINGLETON_EXPORTS

#define SINGLETON_API __declspec(dllexport)

#else

#define SINGLETON_API __declspec(dllimport)

#endif

这样在test.exe中使用该函数时,就不会再产生一个副本了,从而保证了我们的应用程序只有一个singleton

转载于:https://my.oschina.net/u/158055/blog/694483

分享到:
评论

相关推荐

    singleton_crash:演示由多个动态库链接的静态库中的单例导致的崩溃

    singleton_crash 演示由多个动态库链接的静态库中的单例导致的崩溃

    单例实现源码singleton-C++

    实现了单例模型。 vs2015的工程

    中间件实例,动态链接库实例及调用实例,静态态链接库实例及调用实例,单接口COM组件,多接口COM组件

    中间件实例,动态链接库实例及调用实例,静态态链接库实例及调用实例,单接口COM组件,多接口COM组件,不同的创建实例及调用实例!

    工程简单重构,封装动态链接库

    工程简单重构,封装动态链接库,讲述一下动态链接库是怎么搭建起来和使用的

    Qt界面加载网络摄像头,并实时显示,两种更新界面的方法

    1、Qt界面加载网络摄像头,并实时...4、本人使用Qt5.10.0、vs2015、opencv3.4.3,必须在运行根目录添加opencv动态库或将此库添加环境变量 5、里面涉及到一些单例模式、类静态成员的用法,后期再整理,供大家共同成长

    VS2019开发简单的C/C++动态链接库并进行调用的实现

    小白提升:VS2019开发简单的C/C++动态链接库并在解决方案中进行调用 一、 vs2019简单动态链接库的开发 1.VS2019新建立一个空项目(DLL1) VS有提供dll项目的模板,可是对于我来说反而搞不懂模板中的文档,于是建立空白...

    Python Cookbook

    17.3 在Python中使用C++库 598 17.4 调用Windows DLL的函数 601 17.5 在多线程环境中使用SWIG生成的模块 603 17.6 用PySequence_Fast将Python序列转为 C数组 604 17.7 用迭代器逐个访问Python序列的元素 608 ...

    jackson-dynamic-filter:一种使用Jackson来动态确定过滤器的简便方法

    因此,此存储库提供了一种动态确定过滤器的简便方法,并且可以与Spring MVC / Spring Boot很好地集成。 对于Spring Boot: 要求Java 8 支持的Spring IO平台: 下载要使用Maven添加依赖项,请使用以下命令: ...

    API设计教程

    讨论各种能够影响良好API设计的C++语言特性,如良好构造函数和操作符风格、命名空间、指针和引用参数的比较、友元的使用以及如何在动态库中导出符号。 第7章:性能。分析API的性能问题并说明如何使用C++构建高性能的...

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part1

    实例128 获取数组中最后一个元素 158 实例129 去除数组中的重复元素 158 实例130 字符串与数组的转换 159 实例131 对数组元素进行随机排序 160 实例132 随机抽取数组中元素 161 实例133 二维数组的输出 162 实例134 ...

    学习C++,学习windows/linux编程,学习网络编程,学习reactor模型,自己实现一遍练手;

    学习C++,学习windows/linux编程,学习网络编程,学习reactor模型,自己实现一遍练手; 包含(以下实现是Windows/Linux平台通用的,美名其曰跨平台) 基本工具库: 日志工具(日志优先级、同步日志、异步日志、带...

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part2

    实例128 获取数组中最后一个元素 158 实例129 去除数组中的重复元素 158 实例130 字符串与数组的转换 159 实例131 对数组元素进行随机排序 160 实例132 随机抽取数组中元素 161 实例133 二维数组的输出 162 实例134 ...

    毕业设计-基于JAVA的系统框架设计与开发(源代码+论文)

    SMART系统是一个新型智能在线考试信息管理系统,该系统主要实现了学生在线考试与...基于WEB的在线考试系统的主要好处是一方面可以动态地管理各种考试信息,只要准备好足够大的题库,就可以按照要求自动生成各种试卷;

    Android代码-DownloadHelper

    AndroidManifest.xml中需要注册权限和service.(读写文件的权限要在代码中动态申请,不要忘记这点了) &lt;!-- 注册service --&gt; 2, 开始/暂停/重启 下载任务。 开始 //先获得这个单例对象 mDownloadHelper...

    2023java最新学习路线.docx

    3. 反射和字节码操作:学习使用Java的反射机制和字节码操作库,实现动态代理、代码生成和运行时修改类的功能。 4. 函数式编程:学习Java 8及更高版本引入的函数式编程特性,如Lambda表达式和Stream API,提升代码...

    java面试题

    Struts1只是在第一次请求的时候创建一个action实例,以后每次相同的请求都直接从内存中去读取,它是单例模式,安全性较差。 Struts2是如何实现MVC模式的? 答:在Struts2里面是将每次页面的请求进行处理,然后将请求...

    二十三种设计模式【PDF版】

    将牛郎织女分开(本应在一起,分开他们,形成两个接口),在他们之间搭建一个桥(动态的结合) 设计模式之 Flyweight(共享元) 提供 Java运行性能,降低小而大量重复的类的开销. C. 行为模式 设计模式之 Command(命令) ...

    java 面试题 总结

    在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告或退出。...

    php网络开发完全手册

    15.4.8 一个完整的查看表中各列属性 15.4.8 的实例 258 15.5 常见问题与解决方案 259 15.6 小结 261 第16章 数据库中的程序逻辑 262 16.1 数据库程序逻辑与PHP程序逻辑的分体 16.1 设计原则 262 16.2 数据库中的程序...

Global site tag (gtag.js) - Google Analytics