C++模板

最近使用了c++模板,觉得非常强大,只是写起来需要掌握一点技巧。大部分模板都是直接把定义写在.h头文件,并且有些人还说这样做的原因是模板不支持分编译,可是以前的编译器对模板的支持不够好吧,但是现在完全可以。

环境:

win7 32旗舰版、VS2010 sp1

1、普通函数模板

define.h文件

1 template<typename T>
2 T GetString(int value);

define.cpp文件

 1 #include "define.h"
 2
 3 template<typename T>
 4 T GetString<T>(int value)
 5 {
 6     return T(value);
 7 }
 8
 9 //偏特化
10 template<>
11 string GetString<string>(int value)
12 {
13     char psz[32] = {0};
14     itoa(value, psz, 10);
15     return string(psz);
16 }
17
18 //偏特化
19 template<>
20 wstring GetString<wstring>(int value)
21 {
22     wchar_t psz[32] = {0};
23     _itow(value, psz, 10);
24     return wstring(psz);
25 }
如果我们直接包含define.h后,使用GetString<int>(100)函数调用,是使用不了的,会产生链接错误,为什么呢?我们上面定了函数模板的通用
实现,但是并没有实例化为一个真正的函数,既然不是函数,编译器当然不会生成代码,所以会出现链接错误;要解决这个问题的最主要就是实例化函
数模板使之成为一个真正的函数,第一种办法是:使用上面偏特化的方法,例如string和wstring类型的偏特化,因为上面已经写了,所以不多说了;
下面说第二种办法:
1 #define TEMPLATE_GET_STRING(T) template T GetString<T>(int value);
2 TEMPLATE_GET_STRING(int)//函数模板实例化
3 // 如果要在dll中导出此函数,我们可以这样
4 template __declspec(dllexport) int GetString<int>(int value);

2、类模板

define.h文件

 1 template<typename T>
 2 class A
 3 {
 4 public:
 5     A()
 6     {
 7         InitValue();
 8     }
 9
10     void InitValue();
11
12     int m_nValue;
13 };

define.cpp文件

 1 template<typename T>
 2 A<T>::A()
 3 {
 4     InitValue();
 5 }
 6
 7 template<>
 8 void A<string>::InitValue()
 9 {
10     m_nValue = 100;
11 }
12
13 template<>
14 void A<int>::InitValue()
15 {
16     m_nValue = 200;
17 }
18
19 // 类模板实例化
20 template
21 A<int>;

3、成员函数模板

define.h文件

1 class B
2 {
3 public:
4     template<typename T>
5     T Get(int index);
6 };

define.cpp文件

 1 //成员函数模板偏特化
 2 template<>
 3 double B::Get<double>(int index)
 4 {
 5     return 2.1;
 6 }
 7
 8 //成员函数模板偏特化
 9 template<>
10 int B::Get<int><int>(int index)
11 {
12     return 1;
13 }
14 </int>
15 //如果类B是一个数据库封装类,我们就可以利用这样的调用方式来获取数据库一条记录中的字段
16
17 B b;
18 b.Get<int>(1);//获取当前记录中第一个字段的值,并转化为int类型
19 b.Get<double>(2)//获取当前记录中第二个字段的值,并转化为double类型

4、将类型与一些数据进行绑定

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

1 class A {
2 public:
3     static A* Create() { return new A(); }
4 };

然后像这样:

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

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

 1 typedef void*(*CreateCallback)(); // 创建函数的指针
 2 class Instance {
 3 public:
 4     /**   注册
 5      *    @T             绑定的类型
 6      *    @callback      对象创建函数
 7      */
 8     template<class T>
 9     static void Register(CreateCallback callback) {
10         m_map.insert(std::make_pair(TypeDefine<T>, callback));
11     }
12
13     /**   创建对象
14      *    @T            创建对象的类型
15      *    @return       创建的对象
16      */
17     template<class T>
18     static T* Create() {
19         std::map<TypeDefineIndifiry, CreateCallback>::iterator iter = m_map.find(TypeDefine<T>);
20         return (T*)iter->second();
21     }
22
23 private:
24     template<class T>
25     static void TypeDefine() {}
26
27     typedef void(*TypeDefineIndifiry)();
28     static std::map<TypeDefineIndifiry, CreateCallback> m_map;
29 };
30 std::map<Instance::TypeDefineIndifiry, CreateCallback> Instance::m_map;

接下来我们使用它:

1 Instance::Register<A>((CreateCallback)A::Create);
2 A* a = Instance::Create<A>();
时间: 2024-10-21 21:58:20

C++模板的相关文章

Vue.js项目模板搭建

前言 从今年(2017年)年初起,我们团队开始引入「Vue.js」开发移动端的产品.作为团队的领头人,我的首要任务就是设计 整体的架构 .一个良好的架构必定是具备丰富的开发经验后才能搭建出来的.虽然我有多年的前端开发经验,但就「Vue.js」来说,仍然是个新手.所幸「Vue.js」有一个配套工具「Vue-CLI」,它提供了一些比较成熟的项目模板,很大程度上降低了上手的难度.然而,很多具体的问题还是要自己思考和解决的. 项目划分 我们公司的H5产品大部分是嵌套在手机客户端里面的页面.每个项目的功能

ac自动机基础模板(hdu2222)

In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey also wants to bring this feature to his image retrieval system. Every image have a long description, when users type some keywords to find the image, th

hdu 2966 In case of failure kdtree模板题

问求每个点距离平方的最小的点 kd-tree模板题…… 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a)) 3 #define debug(x) cerr<<#x<<"=="<<(x)<<endl 4 using namespace std; 5 typedef long long ll; 6 typedef pair<int,int>

eclipse添加xml模板

//因为学javaee,中框架,,感觉配置文件好多, window-preferences-xml-xmlfiles-editor-templates-选中模板,-edit

POJ3528 HDU3662 三维凸包模板

POJ3528 HDU3662 第一道题 给定若干点 求凸包的表面积,第二题 给定若干点就凸包的面数. 简单说一下三维凸包的求法,首先对于4个点假设不共面,确定了唯一四面体,对于一个新的点,若它不在四面体内,为了让它进入凸包, 则对于所有凸包上的边,若边的一面是该点可以看到的而另一面看不到,则该点与该边构成的面要加入凸包. 模板代码非常清晰, #include<stdio.h> #include<algorithm> #include<string.h> #includ

zabbix用自带的模板监控mysql

先看一下zabbix自带的mysql模板监控项: #很少是吧,没事生产环境一般我们不用,下一篇将介绍生产环境用的另一种mysql监控. 配置zabbix自带的模板监控mysql数据库:

小程序砸金蛋、外卖模板上线啦,快到酷客多商户后台更新!

最近,微信小程序官方发文不断,又开放十几项接口,逐步给企业主带来跟多福利.于此同时,酷客多研发团队也保持着一贯的研发和版本迭代速度,此次版本主要新增幸运砸金蛋.外卖模板.意见反馈三个模块 1.新增幸运砸金蛋,大奖中不停 通过此功能可增加平台趣味性,增强用户粘性,刺激用户二次消费,是与用户互动的一大利器. 2新增外卖模板,外卖送起来 此模板是餐饮企业的福利,可在注册或者酷客多商户管理后台直接选择此模板,瞬间让您的小程序首页变的高大上,从此再也不用担心第三方外卖平台高额的佣金和账期了,因为酷客多只提

C++学习笔记50:队列类模板

队列是只能向一端添加元素,从另一端删除元素的线性群体 循环队列 在想象中将数组弯曲成环形,元素出队时,后继元素不移动,每当队尾达到数组最后一个元素时,便再回到数组开头. 队列类模板 //Queue.h #ifndef QUEUE_H #define QUEUE_H #include <cassert> //类模板的定义 template <class T, int SIZE = 50> class Queue { private: int front, rear, count; T

ReactJS React+Redux+Router+antDesign通用高效率开发模板,夜间模式为例

工作比较忙,一直没有时间总结下最近学习的一些东西,为了方便前端开发,我使用React+Redux+Router+antDesign总结了一个通用的模板,这个技术栈在前端开发者中是非常常见的. 总的来说,我这个工程十分便捷,对于初学者来说,可能包含到以下的一些知识点: 一.React-Router的使用 Router是为了方便管理组件的路径,它使用比较简单,一般定义如下就行,需要注意的是,react-router的版本有1.0-3.0,各个版本对应的API大致相似,但也有不同,我使用的是2.X的,

Django的模板系统

模板系统介绍 模板系统的组成:HTML代码和逻辑控制代码 逻辑控制代码可以理解是django模板语言 django的模板语言组成 变量(使用双大括号来引用变量): 标签(tag)的使用(使用大括号和百分比的组合来表示使用tag) 模板继承 模板语言之变量 语法: {{var_name}} var_name 指变量名 使用模板语言之前: 先介绍template对象和Context对象 进入django的项目的交互环境 python manange.py shell >>> from dja