C++中的模板(template)

网上我最喜欢的技术文章是类似某何君所著“CVS快速入门”或者“UML reference card”之类,简短扼要,可以非常快的领着你进入一个新天地。而对于比较长的文章我通常是将其保存到硬盘上,然后准备着“以后有时间”的时候再看,但它们通常的命运都是“闲坐说玄宗”,直到某一天在整理硬盘时将它们以“不知所云”入罪,一并删除。

这篇小文主要是针对刚刚接触模板概念的读者,希望能帮助读者学习模板的使用。为了避免本文也在诸公的硬盘上遭逢厄运,我决定写的短些。“以后有时间”的时候再补充些内容。

1. 简介

模板是C++在90年代引进的一个新概念,原本是为了对容器类(container classes)的支持[1],但是现在模板产生的效果已经远非当初所能想象。

简单的讲,模板就是一种参数化(parameterized)的类或函数,也就是类的形态(成员、方法、布局等)或者函数的形态(参数、返回值等)可以被参数改变。更加神奇的是这里所说的参数,不光是我们传统函数中所说的数值形式的参数,还可以是一种类型(实际上稍微有一些了解的人,更多的会注意到使用类型作为参数,而往往忽略使用数值作为参数的情况)。

举个常用的例子来解释也许模板就从你脑袋里的一个模糊的概念变成活生生的代码了:

在C语言中,如果我们要比较两个数的大小,常常会定义两个宏:

#define min(a,b) ((a)>(b)?(b):(a))

#define max(a,b) ((a)>(b)?(a):(b))

这样你就可以在代码中:

return min(10, 4);

或者:

return min(5.3, 18.6);

这两个宏非常好用,但是在C++中,它们并不像在C中那样受欢迎。宏因为没有类型检查以及天生的不安全(例如如果代码写为min(a++, b--);则显然结果非你所愿),在C++中被inline函数替代。但是随着你将min/max改为函数,你立刻就会发现这个函数的局限性 —— 它不能处理你指定的类型以外的其它类型。例如你的min()声明为:

int min(int a, int b);

则它显然不能处理float类型的参数,但是原来的宏却可以很好的工作!你随后大概会想到函数重载,通过重载不同类型的min()函数,你仍然可以使大部分代码正常工作。实际上,C++对于这类可以抽象的算法,提供了更好的办法,就是模板:

template <class T> const T & min(const T & t1, const T & t2) {
  return t1>t2?t2:t1;
}

这是一个模板函数的例子。在有了模板之后,你就又自由了,可以像原来在C语言中使用你的min宏一样来使用这个模板,例如:

return min(10,4);

也可以:

return min(5.3, 18.6)

你发现了么?你获得了一个类型安全的、而又可以支持任意类型的min函数,它是否比min宏好呢?

当然上面这个例子只涉及了模板的一个方面,模板的作用远不只是用来替代宏。实际上,模板是泛化编程(Generic Programming)的基础。所谓的泛化编程,就是对抽象的算法的编程,泛化是指可以广泛的适用于不同的数据类型。例如我们上面提到的min算法。

时间: 2024-11-03 21:00:21

C++中的模板(template)的相关文章

C++:模板(template)中typename的使用方法

声明template参数时, 前缀关键字class和typename可以互换; 使用关键字typename标识嵌套从属类型名称, 但不需在基类列表和成员初始化列表内使用. 从属名称(dependent names): 模板(template)内出现的名称, 相依于某个模板(template)参数, 如T t; 嵌套从属名称(nested dependent names):从属名称在class内呈嵌套装, 如T::const_iterator ci; 非从属名称(non-dependent nam

C++ - 模板(template)中typename的使用方法

声明template参数时, 前缀关键字class和typename可以互换; 使用关键字typename标识嵌套从属类型名称, 但不需在基类列表和成员初始化列表内使用.   从属名称(dependent names): 模板(template)内出现的名称, 相依于某个模板(template)参数, 如T t; 嵌套从属名称(nested dependent names):从属名称在class内呈嵌套装, 如T::const_iterator ci; 非从属名称(non-dependent n

C++中函数模板(function template) 详解

C++的模板(template)是泛型编程(generic programming)的基础; 面向对象编程 是 运行(run time)时 知道类型(type); 泛型编程 是编译(compilation) 知道类型; 函数模板(function template)包含模板参数列表(template parameter list); 每个参数类型之前必须包含关键字typename或class, 尽量使用typename, 表达意思更加明确; 非类型模板参数(Nontype Template Pa

PHP中的模板技术

综述: 在多人开发大型PHP项目时,模板技术非常有用,它可以分开美工和程序员的工作,并且方便界面的修改和完善:不仅如此,利用模板技术,我们还可以简单有效地定制或者修改站点.现在我们将要以PHPLIB的模板为例子讲述如何在PHP中应用模板技术. 如何使用PHPLIB模板? 设我们有一个模板, 名为UserTemp,路径为/home/user_dir/user_temp/,它的内容如下: 你订购的是:{Product} 大括号表示Product是一个模板变量. 然后我们编写如下的

c++问题-c++中关于模板的一些小细节

问题描述 c++中关于模板的一些小细节 今天突然看到一细节,在模板中 template和template的区别是什么 解决方案 C++中typename和class的区别http://blog.163.com/susu_sf/blog/static/171060253201092233759957/ http://blog.csdn.net/dick_china/article/details/4522253 解决方案二: C++中typename和class的区别http://blog.163

Django中的模板

通过<如何创建一个Django网站>大概清楚了如何创建一个简单的 Django 网站,这篇文章主要是在此基础上介绍 Django 中模板相关的用法. 视图中使用模板 在<如何创建一个Django网站>中使用模板的方式如下: from django.http import HttpResponse from django.template import RequestContext, loader from polls.models import Question def index

c++ 函数模板重载-关于c++中函数模板的重载问题

问题描述 关于c++中函数模板的重载问题 直接上代码(简单),enter code here template< class T > void test(T x){ cout<<x<<endl; } void test(int); int main(){ int x = 1; test(x); } 上述程序使用非模板函数对函数模板test进行重载:按照书中的说法-这个非模板函数可以只声明原型,然后借用模板中定义的函数体. 但是链接的时候找不到那个非模板函数的定义(使用的

ES6中的模板字符串和新XSS Payload

ES6中的模板字符串和新XSS Payload 作者:负羽 众所周知,在XSS的实战对抗中,由于防守方经常会采用各种各样严格的过滤手段来过滤输入,所以我们使用的XSS Payload也会根据实际情况作出各种各样的调整,最常见的如避免括号,避免引号,避免关键字等,以绕开过滤函数的检查,从而成功将代码注入到网页中运行. 在传统的XSS Payload变形中,常用的无非有以下几种: 1. 使用String.fromCharCode来避免关键字,如String.fromCharCode(97,108,1

c++-在windows下mingw对类中含有模板函数报错

问题描述 在windows下mingw对类中含有模板函数报错 在windows下用mingw 进行编译报错,说解析模板参数列表报错.在linux下编译正确. 代码我已经简化: #include <iostream> using namespace std; class Point{ public: //实现setPoint函数 void setPoint(int x, int y){ xPos = x; yPos = y; } //实现printPoint函数 void printPoint(