(转载请注明原创于潘多拉盒子)

C++的模板可以帮助我们编写适合不同类型的模板类,给代码的复用性提供了极大的方便。近来写了一个涉及单例的C++模板类,简化下来可以归结为以下的代码:

template <typename T>
class Singleton
{
public:
// 此处省去了多线程安全锁
static T* getInstance()
{
    static T t;
    return &t;
  }
};

  那么如果希望对某个work horse类,比如叫做Foo,定义一个Singleton,就会很容易啦:

Foo* foo = Singleton<Foo>::getInstance();

 注意这里不需要自己释放foo,因为它不是new出来的。

如果代码被编译成“一个”so(dll)或可执行文件,这里的Singleton得到的对象却是是单例的,也就是说,某一种类型得到的对象地址是确定的。

但是,如果同一个类型的单例在不同的so(dll,可执行文件)中使用,那么得到的同一个类型的单例对象,其地址也是不一样的。比如

libfoo.so文件中的如下代码:

Foo* foo = Singleton<Foo>::getInstance();
std::type_info fooType = typeid(Singleton<Foo>);

  和libbar.so中的另一端代码:

Foo* bar = Singleton<Foo>::getInstance();

std::type_info barType = typeid(Singleton<Foo>);

  其中foo和bar的地址是不同的!他们并不是真正的单例。

为什么呢?原因是模板是编译的时候实例化成“真正的类”的,而在两个不同的so编译生成的过程中,编译器进行了两个不同的实例化过程,他们被实例化成了不同的类。也不是完全不同,但有部分是不同的。

比如,对上述两个so,如果去测试两个Singleton类型是否为同一类型(RTTI):

if (fooType == barType)

  那么该测试会返回false。但是,如果测试两个类型的名字是否相等:

if (strcmp(fooType.name(), barType.name()) == 0)

  该测试则会返回true。

这说明,两个类型虽然type_info不同,但名字却是相同的。

在Google上搜了一下相关的信息,发现这确实是一个难题。因此,用模板来实现单例,是无法跨so的。当然,这里不是真正用模板来实现单例,只是用这个例子来演示模板的RTTI特性。

C++中模板单例的跨SO(DLL)问题:RTTI,typeid,static,单例的更多相关文章

  1. form表单提交没有跨域问题,但ajax提交存在跨域问题

    浏览器的策略本质是:一个域名下面的JS,没有经过允许是不能读取另外一个域名的内容,但是浏览器不阻止你向另外一个域名发送请求. 所以form表单提交没有跨域问题,提交form表单到另外一个域名,原来页面 ...

  2. 多个so中模板单例的多次实例化

    在Android打包项目时,发现登录功能不能使用了,logcat中也没发现什么问题,最后一行一行log定位到了问题.原来是一个so文件中的构造函数被初始化二次!   这个单例是通过继承模板来实现的(暂 ...

  3. 关于 underscore 中模板引擎的应用演示样例

    //关于 underscore 中模板引擎的应用演示样例 <!doctype html> <html> <head> <meta charset=" ...

  4. jQuery中利用JSONP解决AJAX跨域问题

    写在前面 跨域的解决方案有多种,其中最常见的是使用同一服务器下的代理来获取远端数据,再通过ajax进行读取,而在这期间经过了两次请求过程,使得获取数据的效率大大降低,这篇文章蓝飞就为大家介绍一下解决跨 ...

  5. Vue中应用CORS实现AJAX跨域,及它在 form data 和 request payload 的小坑处理

    基本概念部分(一):理解CORS 说道Vue的跨域AJAX,我想先梳理一遍CORS跨域,"跨域资源共享"(Cross-origin resource sharing),它是一个W3 ...

  6. tornado学习笔记11 Web应用中模板(Template)使用应用实践

    上一篇中(Web应用中模板的工作流程分析),已经分析了模板的渲染流程,以及相关参数获取及设置原理.这篇主要讲述模板在实际应用案例. 11.1 需求 根据用户输入的两次密码,判断两次密码是否一致,并将判 ...

  7. wpf 获取datagrid中模板中控件

    //获取name为datagrid中第三列第一行模板的控件 FrameworkElement item = dataGrid.Columns[].GetCellContent(dataGrid.Ite ...

  8. [转]js中几种实用的跨域方法原理详解

    转自:js中几种实用的跨域方法原理详解 - 无双 - 博客园 // // 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同 ...

  9. c++中模板是什么?为什么要定义模板?

    一.c++中模板是什么? 首先: int Max(int x, int y) { return x > y ? x : y; } float Max(float a,float b) { ret ...

  10. springboot中通过cors协议解决跨域问题

    1.对于前后端分离的项目来说,如果前端项目与后端项目部署在两个不同的域下,那么势必会引起跨域问题的出现. 针对跨域问题,我们可能第一个想到的解决方案就是jsonp,并且以前处理跨域问题我基本也是这么处 ...

随机推荐

  1. asp.net MVC发布iis无法加载css,js和图片

    今天真够郁闷的,遇到了在本地能运行的项目到了iis服务器那里就不行了,无法加载css,js和图片,这里说清楚一下先,关于asp.net 的MVC中这样的情况其实不少,但是之前遇到的是在visual s ...

  2. 004 Ajax中传输格式为JSON

    一: 1.介绍 2.嵌套 3.json解析 4.优缺点 二:json功能程序测试 1.设计 2.程序 <!DOCTYPE html> <html> <head> & ...

  3. 纯CSS仿制Google女生节Doodle

    看到google今天的女生节Doodle,自己用纯css仿制一个,送给老妈.老婆.女儿. 大家可以点这里在线观看效果,点这里下载收藏效果. 实现原理 1.利用checkbox侦听处理单击事件. 2.单 ...

  4. MDP中值函数的求解

    MDP概述   马尔科夫决策过程(Markov Decision Process)是强化学习(reinforcement learning)最基本的模型框架.它对序列化的决策过程做了很多限制.比如状态 ...

  5. Outlook数据提取工具readpst

    Outlook数据提取工具readpst   Outlook是Windows常用的邮件客户端.它将用户的信息保存到.pst文件中,如邮件.约会.日历.联系人等信息.为了便于查看这些信息,Kali Li ...

  6. apache 监控

    当前加载模块 [root@controller01 ~]# httpd -lCompiled in modules: core.c mod_so.c http_core.c 当前版本[root@con ...

  7. JavaScript 数据类型 (续)

    JavaScript 对象 对象由花括号分隔.在括号内部,对象的属性以名称和值对的形式 (name : value) 来定义.属性由逗号分隔: var person={firstname:" ...

  8. C# 简单读写ini文件帮助类 INIHelp

    软件里需要读取一些初始化信息, 决定用ini来做,简单方便. 于是查了一写代码,自己写了一个帮助类. INI文件格式是某些平台或软件上的配置文件的非正式标准, 以节(section)和键(key)构成 ...

  9. Java Jxl

    Java Jxl (转自http://blog.csdn.net/laliocat/article/details/50580020) 1 开发调研1.1 需求描述MS的电子表格(Excel)是Off ...

  10. python开发_HTMLParser_html文档解析

    ''' 在HTMLParser类中,定义了很多的方法,但是很多方法都是没有实现的, 这需要我们继承HTMLParser类,自己去实现一些方法 如: # Overridable -- handle st ...