有时候我们需要将类型与一些数据进行绑定,例如我们一般通过单例,将字符串与一个函数关联(一般称之为注册),之后通过字符串创建相关联的对象

class A {
public:
static A* Create() { return new A(); }
};

然后像这样:

Instance::Register("A", A::Create);
A* a = Instance::Create("A");

用字符串进行绑定,不是很方便,如果字符串拼写错了,在整个编译期不会有任何提示,而且字符串是没有代码自动提示的,这样出错率大大增加了,当然你可以复制/粘贴;如果我们能够将一个类型与数据进行绑定,通过类型获取与之相关的数据,一是类型有代码自动提示的(一般拼写前几个字符就可以完成整个输入),及时你自己拼写出错了,没有定义这个类型,编译器编译时也会报错。这里我们使用函数模板,理论上不同的类型,会实例化为不同的函数,我们可以使用函数地址作为标识这个类型的key。

TypeBind.h

#ifndef _Type_Bind_H_
#define _Type_Bind_H_ #include <assert.h>
#include <map> template<class _Value>
class TypeBind {
public:
template<class _Type>
void bind(_Value value) {
m_map.insert(std::make_pair(TypeDefine<_Type>, value));
} template<class _Type>
_Value& find() {
std::map<TypeDefineIndifiry, _Value>::iterator iter = m_map.find(TypeDefine<_Type>);
assert(iter != m_map.end());
return iter->second;
} private:
template<class T>
static void TypeDefine(char _ch) { static char ch = _ch; }
typedef void(*TypeDefineIndifiry)(); std::map<TypeDefineIndifiry, _Value> m_map;
}; #endif
这里我们使用的是
“template<class T> static void TypeDefine(char _ch) { static char ch = _ch; }“函数
而没有使用
"template<class T> static void TypeDefine() {}"函数
原因是生成Release版本时,编译器会进行优化,如果函数的内容是一致的,最后只会生成一个函数(函数的名称不相同,但是内容是一样,也是相同的结果),如果所有类型的函数地址是一致的,就无法使用给每个类型一个标识(函数地址)

test.cpp

#include "TypeBind.h"

typedef void*(*CreateCallback)(); // 创建函数的指针
class ObjectCreateFactory {
public:
/** 注册
* @T   绑定的类型
* @callback   对象创建函数
*/
template<class T>
void Register(CreateCallback callback) {
m_map.bind<T>(callback);
}
/** 创建对象
* @T 创建对象的类型
* @return 创建的对象
*/
template<class T>
T* Create() {
CreateCallback callback = m_map.find<T>();
return (T*)callback();
} static ObjectCreateFactory& Instance() {
static ObjectCreateFactory* factory = nullptr;
if (!factory)
factory = new ObjectCreateFactory();
return *factory;
}
private:
ObjectCreateFactory() {}
TypeBind<CreateCallback> m_map;
}; class A {
public:
static A* Create() { return new A(); }
}; class B {
public:
static B* Create() { return new B(); }
};
// 注册
ObjectCreateFactory::Instance().Register<A>((CreateCallback)A::Create);
ObjectCreateFactory::Instance().Register<B>((CreateCallback)B::Create);
// 创建
A* a = ObjectCreateFactory::Instance().Create<A>();
B* b = ObjectCreateFactory::Instance().Create<B>();

C++模板之类型与数据绑定的更多相关文章

  1. C++11 图说VS2013下的引用叠加规则和模板参数类型推导规则

    背景:    最近在学习C++STL,出于偶然,在C++Reference上看到了vector下的emplace_back函数,不想由此引发了一系列的“探索”,于是就有了现在这篇博文. 前言:     ...

  2. C++模板参数类型(转载)

    实际上有三种类型模板参数:类型模板参数.无类型模板参数和模板模板参数(以模板作为模板的参数). .类型模板参数 类型模板参数是我们使用模板的主要目的.我们可以定义多个类型模板参数: template& ...

  3. 《深入实践C++模板编程》之三——模板参数类型详解

    非类型模板参数 和 模板型模板参数 整数以及枚举类型:指向对象或者函数的指针:对对象或函数的引用:指向对象成员的指针.统称为非类型模板参数. 模板型模板参数,是指模板参数还可以是一个模板.   1.整 ...

  4. AngularJS开发指南12:AngularJS的模板,CSS,数据绑定详解

    模板 AngularJS模板是一种声明式的规则.它包含了模型和控制器的信息,最后会被渲染成用户在浏览器中看到的视图.它是静态的DOM,包含HTML,CSS和AngularJS指定的元素和属性.Angu ...

  5. c++ 模板 指针类型偏特化

    一步步来,先简单点. 目标:我们要实现一个模板类,例化后,可以通过get_val获取到值,通过get_ptr获取到指针.具体什么意思结合例子来看看吧. 例子: struct A{ int data; ...

  6. c++ 使用模板按类型统计stl多维容器中元素的数量

    struct ItemCounter{template<typename T1, typename T2, typename = typename std::enable_if<!std: ...

  7. C++11 引用叠加规则和模板参数类型推导规则

    http://zm8.sm-img2.com/?src=http%3A%2F%2F***%2FArticle%2F38320&uid=57422b713ac761e653af7b327bfd9 ...

  8. FlatBuffers入门

    1.下载flatbuffers 从https://github.com/google/flatbuffers地址下载flatbuffers-master.zip文件. 2.编译flatbuffers ...

  9. GridView的七种数据绑定列的类型

    1.BoundField 用于显示普通文本,是默认的数据绑定列的类型,一般自动生成的列就是该类型,需要注意是DataFormatString属性,该属性可以设置显示的格式,常见格式有:{0:C} 设置 ...

随机推荐

  1. 5、范围标签<fieldset></fieldset>

    <fieldset style="border:0;border:1px solid red;"> <legend style="background- ...

  2. <hdu-2032>杨辉三角

    这是杭电hdu上杨辉三角的链接:http://acm.hdu.edu.cn/showproblem.php?pid=2032  Problem Description: 还记得中学时候学过的杨辉三角吗 ...

  3. Error pulling origin: error: Your local changes to the following files would be overwritten by merge

    Git在pull时,出现这种错误的时候,可能很多人进进行stash,相关stash的请看:Error pulling origin: error: Your local changes to the ...

  4. from表单实现无跳转上传文件,接收页面后台数据。

    本文基于我刚写的http://www.cnblogs.com/iwang5566/p/6287529.html进行了简单的扩展,实现页面无跳转表单数据提交,并接收后台返回的数据. 下载好,上一篇文章d ...

  5. Debian搭建PPTPD

    先安装pptpd: apt-get install pptpd 编辑 /etc/pptpd.conf #取消下面两行的注释,在文件的底部. # localip 192.168.0.1 # remote ...

  6. C# .NETWEB开发6大内置对象

    ASP.NET 内置对象包括 1.Response 2.Request  3.Server  4.Application   5.Session   6.Cookie 1  Request对象主要是让 ...

  7. archive log

    1.查看归档模式 2.查看归档文件所在位置 3.完全恢复和不完全恢复 完全恢复:找到问题产生的时间点,在时间点之后的数据也能同时保留 不完全恢复:只能恢复到产生问题的那个时间点的数据状态. 4.非归档 ...

  8. C#入门经典中的SelectionFont属性为null

    14.6.2.richtextbox控件: private void buttonbold_click(object sender, eventargs e)        {            ...

  9. Servlet综述

    Servlet 是在服务器上运行的小程序.这个词是在 Java applet 的环境中创造的.虽然后者已很少被使用,但 servlet 却发展的很好.是一般面试都会常考的知识. 由来 servlet ...

  10. 淘淘商城_day09_课堂笔记

    今日大纲 实现购物车 基于Mysql实现读写分离 购物车 需求描述 用户可以在登录状态下将商品添加到购物车 用户可以在未登录状态下将商品添加到购物车 用户可以使用购物车一起结算下单 用户可以查询自己的 ...