在 C++ 中,模板分为函数模板和类模板两种。函数模板是用于生成函数的,类模板则是用于生成类的。

函数模板&模板函数     类模板&模板类  必须区分概念

函数模板是模板,模板函数时具体的函数

类模板是模板,模板类时具体的类

由函数模板实例化而得到的函数称为模板函数

由类模板实例化得到的类叫模板类

一.函数模板

函数模板的基本写法为:
template <typename 类型参数1, typename 类型参数2, ...> 

返回值类型  函数模板名(形参表)

{

    函数体

}

其中的 typename 关键字也可以用 class 关键字替换,例如:

template <class 类型参数1, class 类型参数2, ...>

举例,求两个值的最大值Max:

#include<iostream>
using namespace std; template <typename T>
T const& Max(T const& a, T const& b)
{
return a < b ? b : a;
} int main()
{
int i = 20;
int j = 30;
int result1 = Max(i, j); //编译到这一句时,编译器自动生成int Max(int, int)函数 double f1 = 12.5;
double f2 = 20.88;
double result2 = Max(f1, f2); //编译到这句时,编译器自动生成double Max(double, double)函数 string s1 = "Hello";
string s2 = "world";
string result3 = Max(s1, s2); //编译到这句时,编译器自动生成string Max(string, string)函数
return 0;
}

模板在定义时,编译器不会对它编译,因为没有一个实体可用。只有在编译到某句代码时,如int result1 = Max(i, j);时,根据模板再将Max(i, j)编译成int Max(int, int)这样具体的函数。

编译器由模板自动生成函数的过程叫模板的实例化。由模板实例化而得到的函数称为模板函数。在大部分编译器中,模板只有在被实例化时,编译器才会检查其语法正确性。如果程序中写了一个模板却没有用到,那么编译器不会报告这个模板中的语法错误

编译器对模板进行实例化时,并非只能通过模板调用语句的实参来实例化模板中的类型参数,模板调用语句可以明确指明要把类型参数实例化为哪种类型。可以用:

函数名<实际类型参数1, 实际类型参数2, ...>

的方式告诉编译器应该如何实例化模板函数。例如下面的程序:

#include<iostream>
using namespace std; template <typename T>
T add(T n)
{
return n+1;
} int main()
{
cout << add(4) / 2 << endl; //正常写法,输出2
cout << add<double>(4) / 2 << endl; //指明要用double来实例化add函数,输出2.5
return 0;
}

第一句正常调用输出2,第二句为编译器指定类型,则输出2.5

二.类模板

人们需要编写多个形式和功能都相似的函数,因此有了函数模板来减少重复劳动;人们也需要编写多个形式和功能都相似的类,于是C++引入了类模板的概念,编译器从类模板可以自动生成多个类,避免了程序员的重复劳动。

类模板的写法如下:
template <class 类形参数1, class 类型参数2, ...>

class 类模板名称

{

    成员函数和成员变量

};

具体如下:

template<class T1, class T2>
class A
{
public:
T1 value1;
T2 value2;
T1 add(T1 a, T2 b);
};

类模板中的成员函数放在类外定义时的语法如下:
template <class 类形参数1, class 类型参数2, ...>

返回值类型  类模板名<class 类塑参数1, class 类型参数2, ...>::成员函数名(形参表)

{

    。。。

}

具体如下:

template<class T1,class T2>
T1 A<T1, T2>::add(T1 a, T2 b)
{
return a + b;
}

用类模板定义对象的写法如下:
类模板名<真实类型参数表> 对象名(构造函数实际参数表);
若构造函数无参的话则为:
类模板名 <真实类型参数表> 对象名;

下面实现一个简单的key,value的键值对----类模板mDictionary

实践中常常会碰到,某项数据记录由两部分组成,一部分是关键字,另一部分是值。关键字用来对记录进行排序和检索,根据关键字能查到值。例如,学生记录由两部分组成,一部分是姓名,另一部分是年纪。要能根据姓名对学生进行查询检索,key就是姓名,value就是年龄。

template<class T1, class T2>
class mDictionary
{
public:
T1 key; //关键字
T2 value; //值
mDictionary(T1 k, T2 v) :key(k), value(v)
{
};
T2 getvalue(T1 k);
}; template<class T1,class T2>
T2 mDictionary<T1, T2>::getvalue(T1 k)
{
if (k == this->key) //如果姓名传进来相同,则返回年龄
{
return this->value;
}
else
{
return 0;
}
} int main()
{
mDictionary<string, int> dic("Bob",22);
std::cout << dic.getvalue("Bob")<<std::endl; //返回22
std::cout << dic.getvalue("Tom") << std::endl; //返回0
return 0;
}

实例化一个类模板时,如第main函数第一行-------mDictionary<string, int>  dic("Bob",22);

真实类型参数表中的参数是具体的类型名,如 string、int 等,它们用来一一对应地替换类模板定义中“类型参数表”中的类型参数。类模板名 <真实类型参数表>就成为一个具体的类的名字,就是mDictionary<string, int>就可以看成一个类型

如有一个类A, 初始化类A的时候,一般都是A  a;  mDictionary<string, int>就等价于A,可以看成一个A类型

编译器编译到这一行时,就会用 string 替换 mDictionary模板中的 T1,用 int 替换 T2,其余部分原样保留,这样就自动生成了一个新的类。这个类的名字编译器是如何处理的不需要知道,可以认为它的名字就是mDictionary<string, int>。也可以说,dic 对象的类型就是 Pair<string, int>。
mDictionary<string, int> 类的成员函数自然也是通过替换 mDictionary模板的成员函数中的 T1、T2 得到的。

编译器由类模板生成类的过程叫类模板的实例化。由类模板实例化得到的类叫模板类。

函数模板作为类模板成员

类模板中的成员函数还可以是一个函数模板。成员函数模板只有在被调用时才会被实例化。例如下面的程序:

#include <iostream>
using namespace std;
template <class T>
class A
{
public:
template <class T2> //定义新类型T2
void Func(T2 t) { cout << t; } //成员函数模板
};
int main()
{
A<int> a;
a.Func('K'); //成员函数模板Func被实例化
a.Func("hello");
return 0;
}

程序的输出结果是:Khello

这个例子与上面例子不同的是,mDictionary中的getvalue是一个类模板中的成员函数,没有定义新的模板,而Func函数是一个新的函数模板,在Func函数上面一句,定义了新类型T2,姑且先这样理解。其实只要了解有这种写法即可,既类模板中还可以定义函数模板。

C++ 函数模板&类模板详解的更多相关文章

  1. tp6源码解析-第二天,ThinkPHP6编译模板流程详解,ThinkPHP6模板源码详解

    TP6源码解析,ThinkPHP6模板编译流程详解 前言:刚开始写博客.如果觉得本篇文章对您有所帮助.点个赞再走也不迟 模板编译流程,大概是: 先获取到View类实例(依赖注入也好,通过助手函数也好) ...

  2. 3.2 STL中的函数对象类模板

    *: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...

  3. C++ - 模板类模板成员函数(member function template)隐式处理(implicit)变化

    模板类模板成员函数(member function template)隐式处理(implicit)变化 本文地址: http://blog.csdn.net/caroline_wendy/articl ...

  4. maven pom文件简单模板和配置详解

    https://blog.csdn.net/earbao/article/details/49924943 maven pom文件简单模板和配置详解

  5. C++函数模板&类模板

    函数模板 模板概念及语法 主要目的,简化代码,减少重复代码.基本语法格式:  template<class T> 或者 template<typename T> //末尾不加分 ...

  6. WordPress函数:get_bloginfo()用法详解

    描述 返回你博客的信息,这些信息可以用在任何地方的 PHP 代码中.这个函数,和 bloginfo() 一样,可以用来在模板文件的任何地方显示你博客的信息. 用法 <?php $bloginfo ...

  7. PHP函数call_user_func和call_user_func_array详解

    今天在群里面,有个叫lewis的在问call_user_func_array的用法,因为之前一直没有用过,也不能说什么,于是看一下手册,发现是这么写的: call_user_func_array (P ...

  8. UML类图详解_关联关系_一对多

    对于一对多的示例,可以想象一个账户可以多次申购.在申购的时候没有固定上限,下限为0,那么就可以使用容器类(container class)来搞,最常见的就是vector了. 下面我们来看一个“一对多” ...

  9. UML类图详解_关联关系_多对一

    首先先来明确一个概念,即多重性.什么是多重性呢?多重性是指两个对象之间的链接数目,表示法是“下限...上限”,最小数据为零(0),最大数目为没有设限(*),如果仅标示一个数目级上下限相同. 实际在UM ...

随机推荐

  1. IK分词器 原理分析 源码解析

    IK分词器在是一款 基于词典和规则 的中文分词器.本文讲解的IK分词器是独立于elasticsearch.Lucene.solr,可以直接用在java代码中的部分.关于如何开发es分词插件,后续会有文 ...

  2. 23种常用设计模式的UML类图

    23种常用设计模式的UML类图 本文UML类图参考<Head First 设计模式>(源码)与<设计模式:可复用面向对象软件的基础>(源码)两书中介绍的设计模式与UML图. 整 ...

  3. hive sparksession查询只显示defalt库问题

    1.spark环境记得拷贝进hive.xml 2.SparkSession.builder().enableHiveSupport()记得加上enableHiveSupport 3.window记得w ...

  4. springboot配置多数据源mybatis配置失效问题

    mybatis配置 #开启驼峰映射 mybatis.configuration.map-underscore-to-camel-case=true #开启打印sql mybatis.configura ...

  5. 【模板篇】A* 寻路算法

    上次在做k短路的时候说到了A*, 但是并没有仔细的研究A*寻路, 毕竟k短路中的A*也不怎么标准… A*寻路的过程网上还是有很多的, 讲得也很清楚, 不妨跟着里面的图示自己动手操作一下, 基本一遍就能 ...

  6. [转]Nginx配置详解

    Nginx是lgor Sysoev为俄罗斯访问量第二的rambler.ru站点设计开发的.从2004年发布至今,凭借开源的力量,已经接近成熟与完善. Nginx功能丰富,可作为HTTP服务器,也可作为 ...

  7. input、textarea等输入框输入中文时,拼音在输入框内会触发input事件的问题

    监听文本输入框的input事件,在拼写汉字(输入法)但汉字并未实际填充到文本框中(选词)时会触发input事件,如图: 但是在很多情况下,只需要输入到输入框的中文字符. 解决办法: 通过查阅资料得知在 ...

  8. QT之QByteArray

    1.拷贝内容到QByteArray 1.使用append函数 //结合结构体的(char*)强制转化使用,command.append((char*)&e2_System_Para_t, si ...

  9. springboot-配置多数据源之番外篇(分包实现)

    场景: 随着业务发展,系统连接多数据库成为常态,继前面AOP的实现方式之后,这里记录一下分包实现的方式. 实现:  1.pom.xml <?xml version="1.0" ...

  10. 解决在Spring整合Hibernate配置tx事务管理器出现错误的问题

    问题描述: Error occured processing XML 'org/aopalliance/intercept/MethodInterceptor'. See Error Log for ...