模板是将具有相似性的类和函数归纳起来构成一个类族或函数族,它可是程序具有通用性。模板分为类模板和函数模板。


目录

(一)函数模板

一般定义形式

模板函数重载

函数模板参数

带有多类型参数的函数模板

(二)类模板

类模板的使用


(一)函数模板

int max(int a,int b);
float max(float a,float b);
double max(double a,double b);

如上这三个重载函数,他们的操作相同,都是求两个数中的最大值。为了避免逐个定义重载函数的繁琐编程,由于函数模板使用通用数据类型定义函数,因此使用函数模板完成这项工作更为简洁和方便

一般定义形式

template<class T(类型参数表)>        //template函数模板关键字;T为通用数据类型
返回类型 FunctionName(数据参数表)     //FunctionName函数模板名
{函数模板定义体;                  //接上,T可为基本数据类型或类类型,需加前缀class和typename
}

例如对之前的三个重载函数进行模板化,为:

template<class T>
T max(T a,T b)
{return a>b?a:b;    //T作为返回类型和参数类型
}

函数模板只是函数的描述,表示它每次能单独处理类型形参表中说明的数据类型。它不是一个实实在在的函数,是以具体类型为实参来生成函数体的模板,编译系统不为其产生任何执行代码。使用函数模板可以根据特定的数据类型,产生一个该模板的实例,该函数可以像普通函数一样调用。

#include <iostream>using namespace std;template<class T>
T abs(T n)
{return (n<0)?-n:n;
}int main()
{int int1 = 5;int int2 = -6;long lon1 = 70000L;long lon2 = -80000L;double dub1 = 9.95;double dub2 = -10.15;//模板函数的实例化cout<<"\nabs("<<int1<<")="<<abs(int1);      //abs<int>cout<<"\nabs("<<int2<<")="<<abs(int2);     //abs<int>cout<<"\nabs("<<lon1<<")="<<abs(lon1);     //abs<long>cout<<"\nabs("<<lon2<<")="<<abs(lon2);        //abs<long>cout<<"\nabs("<<dub1<<")="<<abs(dub1);        //abs<double>cout<<"\nabs("<<dub2<<")="<<abs(dub2);      //abs<double>cout<<endl;return 0;
}结果
abs(5)=5
abs(-6)=6
abs(70000)=70000
abs(-80000)=80000
abs(9.95)=9.95
abs(-10.15)=10.15
请按任意键继续. . .

模板函数重载

在编译程序时,输入参数的类型与重载函数的参数类型隐式转换后一致时,调用重载函数,否则调用模板函数(由于博客和书的结论不太一样,并且不知道该听谁的,于是。。。自己总结了)。

#include<iostream>
using namespace std;template<typename T>
T Max(T a, T b) {cout << "\nT Max(T a,T b)" << endl;return a > b ? a : b;
}int Max(int a, int b) {cout << "\nint Max(int a,int b)" << endl;return a > b ? a : b;
}template<typename T>
T Max(T a, T b,T c) {cout << "\nT Max(T a,T b,T c)" << endl;return Max(Max(a, b), c);
}
int main() {int a = 1;int b = 2;cout << Max(a, b) << endl;           //当函数模板和普通函数模板都符合时,优先选择普通函数cout << Max<>(a, b) << endl;         //若显示使用函数模板,则使用<>类型列表cout << Max(3.0, 4.0) << endl;       //如果函数模板可以产生一个更好的匹配,则选择模板cout << Max(5.0, 6.0, 7.0) << endl;  //重载cout << Max('a', 100) << endl;       //调用普通函数可以隐式类型转换return 0;
}结果
int Max(int a,int b)
2T Max(T a,T b)
2T Max(T a,T b)
4T Max(T a,T b,T c)T Max(T a,T b)T Max(T a,T b)
7int Max(int a,int b)
100
请按任意键继续. . .

函数模板参数

函数模板中的数据形参分为:

(1)引用型参数:可提高参数传递效率。

  • 一般引用型参数:template<class T>T max(T &a,T &b);      函数执行过程中,其数据形参的改变会影响数据实参的改变。
  • 常量引用型参数:template<class T>T max(const T &a,const T &b);        引用型参数前用 const 限定,最常使用(考虑参数传递效率和安全性)。

(2)非引用型参数: template<class T>T max(T a,T b);

带有多类型参数的函数模板

形式如下:

template<class T1,class T2,class T3...>
[return-type] function_name(T1 param1,T2 param2...);
//return-type 为返回类型,既可以是一个具体的类型,也可以是 T1、T2中的通用数据类型。Template<class TRetun, class TArg>
TRetun max(TArg a,TArg b)
{return a > b ? a : b;
}
#include <iostream>using namespace std;template<class T1, class T2> void display(T1 x,T2 y)
{cout<<x<<" "<<y<<endl;
}int main()
{char c = 'A';char str[] = "This is a test";int n = 10;float x = 1.5;double z = 3.1415926;//两个参数类型相同display(c, char(c + 2));display(str, str);display(n, 2 * n);display(x, 2 * x);display(z, 2 * z);cout<<"------------------------"<<endl;//两个参数类型不同display(c, str);display(str, c);display(n, str);display(str, 2 * x);display(z, n);return 0;
}结果
A C
This is a test This is a test
10 20
1.5 3
3.14159 6.28319
------------------------
A This is a test
This is a test A
10 This is a test
This is a test 3
3.14159 10
请按任意键继续. . .

(二)类模板

使用模板生成对象时自动创建该模板的一个实例——模板类,也可以显式声明模板类。模板类主要用于容器类,这些类可以包含以特定方式组织起来的给定类型的对象集。例如数组、堆栈、链表,他们所使用的存储方式独立于操作对象的类型。类模板提供的工具,可以定义存储任意类型的对象的容器,模板的参数可用于指定容器存储的对象类型。

类模板定义及实现的一般形式如下:

template<类型形式参数表> class className
{//类声明体
};
template<类型形式参数表>
返回类型className<类型名表>::MemberFuncName1(形式参数表)
{//成员函数定义体
}
...
template<类型形式参数表>
返回类型className<类型名表>::MemberFuncNameN(形式参数表)
{//成员函数定义体
}

定义和实现一个单向链表的模板类:

//list.h
#include <iostream>
using namespace std;template<class T> class List
{
public:List();void Add(T&);                 //添加结点void Remove(T&);              //删除结点T* Find(T&);                  //查找结点void PrintList();             //打印链表~List();
protected:struct Node                       //结构结点{Node* pNext;T* pT;};Node *pFirst;                    //链首节点指针
};template<class T>List<T>::List()
{pFirst = 0;
}template<class T> void List<T>::Add(T& t)  //头插法
{Node* temp = new Node;            //从堆空间中申请一个结点temp->pT = &t;                 //将T对象挂载在这个节点上temp->pNext = pFirst;         //将该结点指向链首的结点pFirst = temp;                    //将该节点成为链首
}template<class T> void List<T>::Remove(T& t)
{Node* q = 0;                  //用来点位待删除的结点if(*(pFirst->pT)==t)           //T类中==需有定义{q = pFirst;pFirst = pFirst -> pNext; //带删除结点在链首时的脱链}else{for(Node* p = pFirst; p -> pNext; p = p -> pNext){if(*(p -> pNext -> pT) == t){q = p -> pNext;p -> pNext = q -> pNext;   break;}}}if(q){delete q -> pT;               //删除节点上的T类对象delete q;                   //删除结点}
}template<class T> T* List<T>::Find(T& t)
{for(Node* p = pFirst; p; p = p -> pNext)if(*(p -> pT) == t)return p -> pT;return 0;
}template<class T> void List<T>::PrintList()
{for(Node* p = pFirst; p; p = p -> pNext)cout<<*(p -> pT)<<" ";cout<<endl;
}template<class T> List<T>::~List()
{Node *p;while( p = pFirst ){pFirst = pFirst -> pNext;delete p -> pT;delete p;}pFirst = 0;
}

类模板的使用

类模板实例创建方式

className<类型实参表> object;

使用实例

// singleList.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <iostream>
#include "list.h"
using namespace std;int main()
{//创建模板类List<float>和该对象List<float> floatList;//创建和遍历浮点链表for(int i = 1; i < 7; i ++)floatList.Add(*new float(i + 0.6));floatList.PrintList();//查找并删除结点float b = 3.6;float* pa = floatList.Find(b);if(pa)floatList.Remove(*pa);floatList.PrintList();return 0;
}结果
6.6 5.6 4.6 3.6 2.6 1.6
6.6 5.6 4.6 2.6 1.6
请按任意键继续. . .

函数模板与类模板定义和使用相关推荐

  1. VS2017 函数模板和类模板的声明、定义和使用

    模板的声明.定义分为两种. 1 将模板的声明和定义都放在头文件中,在主程序的文件中包含此头文件即可 2 将模板的声明和定义分开编写. 在<C++ primer>教材中,将模板的声明和定义分 ...

  2. [C++再学习系列] 函数模板和类模板

    函数模板和类模板 C++ 提供类模板和函数模板.函数模板允许重载 ,而类模板不允许重载(类无重载概念).类模板可以进行全特化和偏特化,而函数模板仅能够全特化 .因此,写一个看似函数模板偏特化的函数模板 ...

  3. 判断exception类型_C++核心准则T.44:使用函数模板推断类模板参数类型(如果可能)...

    T.44: Use function templates to deduce class template argument types (where feasible) T.44:使用函数模板推断类 ...

  4. c++函数模板和类模板

    函数模板和类模板 前言 C++提供两种模板机制:函数模板.类模板 类属 -- 类型参数化,又称参数模板 前言 C++提供了函数模板(function template).所谓函数模板,实际上是建立一个 ...

  5. 类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器

     1.第一个最简单的类模板案例 #include "mainwindow.h" #include <QApplication> #include <QPush ...

  6. C++ 泛型编程(一):模板基础:函数模板,类模板,模板原理,模板匹配规则

    类模板 函数模板 泛型编程 泛型编程,泛型即是指具有在多种数据类型上皆可操作的含义,其实就是能够帮助开发者编写完全一般化并可重复使用的算法,同样的工作不需要做多次,同样的算法针对不同的类型也不应该写多 ...

  7. C++ 泛型编程(一):模板基础:函数模板、类模板、模板推演成函数的机制、模板实例化、模板匹配规则

    文章目录 泛型编程 函数模板 函数模板实例化 隐式实例化 显式实例化 函数模板的匹配规则 类模板 类模板的实例化 泛型编程 泛型编程旨在削减重复工作,如: 将一个函数多次重载不如将他写成泛型. voi ...

  8. 函数模板和类模板的使用

    函数模板 //交换 int 变量的值 void Swap(int *a, int *b){ int temp = *a; *a = *b; *b = temp; } //交换 float 变量的值 v ...

  9. C++基础:模板,函数模板和类模板

    文章目录 1. 函数模板 2. 类模板 3. 模板特化 3.1 函数模板特化 3.2 类模板特化 4. 非类型模板参数 模板是允许函数或类通过泛性的形式表现或运行的特性 1. 函数模板 模板可以使函数 ...

最新文章

  1. 事实证明,OpenCV中对RGB图像数据的存储顺序是BGR,而且Scalar()的顺序也是B,G,R
  2. 大型网站架构演化历程
  3. (转)OpenSSL命令---pkcs12
  4. Kubernetes的Device Plugin机制源码解析
  5. Redis构建分布式锁——Redlock
  6. Win32ASM学习[13]:移位指令SHL,SHR,SAL,SAR,ROL,ROR,RCL,RCR,SHLD,SHRD
  7. 对食材的敬畏之心极致产品_这些数据科学产品组合将给您带来敬畏和启发(2020年中的版本)
  8. 前端学习(2665):完成vue3.0的todolist添加
  9. tomcat常用功能
  10. linux运维、架构之路-Zabbix监控
  11. mysql 索引 lt =_MySQL索引相关
  12. 访问日志不记录静态文件、访问日志切割、静态元素过期时间
  13. hash存储结构【六】
  14. 简单python代码实例_求简洁优美的python代码例子、片段、参考资料
  15. AndroidStudio_安卓原生开发_自定义单选列表Spinner绑定自定义数据类型---Android原生开发工作笔记143
  16. hung task日志linux,Linux Kernel Crash--hung_task_timeout_secs
  17. Java Web(十) JDBC的增删改查,C3P0等连接池,dbutils框架的使用
  18. 思科交换机基本配置命令
  19. c语言 四层电梯算法,电梯算法c语言
  20. ubuntu hashcat 安装

热门文章

  1. Python下安装谷歌插件
  2. 《如何白手起家挣到一百万?》学习笔记
  3. GNSS原理及技术(二)——卫星定位原理
  4. Anaconda+Tushare安装运行宝笈
  5. 详解央行数字货币和数字票据交易平台架构(多图)
  6. 脱硫塔烟囱隧道用乙烯基玻璃鳞片防腐面漆 可耐200℃高温
  7. 读书有益——》小朋友的诗(五)
  8. python 当当京东比价
  9. 一月总结:关于读书,关于英语,关于梦想
  10. python栈的实现与应用