为什么须要模板?

我们已经学过重载(Overloading),对重载函数而言,C++ 通过函数參数(參数个数、參数类型)的正确匹配来调用重载函数。比如。为求两个数的最大值,我们定义 max () 函数须要对不同的数据类型分别定义不同重载(Overload)版本号。

//函数1
int max(int x, int y);
{
return(x>y)? x:y ;
} //函数2
float max( float x, float y)
{
return (x>y)? x:y ;
} //函数3
double max(double x, double y)
{
return (c>y)?x:y ;
}

如今。我们再又一次审视上述的 max() 函数,它们都具有相同的功能,即求两个数的最大值,是否能仅仅写一套代码解决问题呢?这样就会避免因重载函数定义不全面而带来的调用错误(如。我们分别定义了 char a,b; 那么在运行 max(a,b) 时 程序就会出错,由于我们未定义char 类型的重载版本号)。

相同的,对于类而言,也存在相同的问题(基本上是反复性的工作):

//对两个整数作比較
class Compare_int
{
public:
Compare(int a,int b){x=a;y=b;}
int max( ) {return(x>y)?x:y;}
int min( ) {return(x<y)? x:y;}
private:
int x,y;
}; //对两个浮点数作比較
class Compare_float
{
public:
Compare(float a,float b) {x=a;y=b;}
float max( ) {return(x>y)?x:y;}
float min( ) {return(x<y)? x:y;}
private:
float x,y;
}

为解决上述问题 C++ 引入模板机制:模板就是实现代码重用机制的一种工具,它能够实现类型參数化,即把类型定义为參数。 从而实现了真正的代码可重用性。模版能够分为两类。一个是函数模版。另外一个是类模版。

函数模板

函数模板的一般形式例如以下:

template <class 形參名, class 形參名, ……> 返回类型 函数名(形參表)

{

//函数定义体

}

当中 template 和 class 是keyword,class 能够用 typename 取代,在这里 typename 和 class 没差别。<> 括号里的參数叫模板形參。模板形參和函数形參非常相像。模板形參不能为空。

一但声明了类模板,函数中使用内置类型的地方都能够使用模板形參名来声明

模板形參须要调用该模板函数时提供的模板实參来初始化模板形參,一旦编译器确定了实际的模板实參类型就称他实例化了函数模板的一个实例。

template <class T> void swap(T& a, T& b)
{
//……
}

当调用这种模板函数时类型 T 就会被被调用时的类型所取代,比方 swap(a,b) 当中 a 和 b 是 int  型,这时模板函数 swap 中的形參 T 就会被 int 所取代,模板函数就变为 swap(int &a, int &b)。而当 swap(c,d) 当中 c 和 d 是 double 类型时,模板函数会被替换为swap(double &a, double &b),这样就实现了函数的实现与类型无关的代码。

演示样例代码例如以下:

#include <iostream>
using std::cout;
using std::endl; //声明一个函数模版,用来比較输入的两个同样数据类型的參数的大小,
//class也能够被typename取代。
//T能够被不论什么字母或者数字取代。 //template <typename T>
template <class T> T max(T x,T y)
{
return(x>y)?x:y;
} int main()
{ int a=2, b=10;
cout<< "较大整数:"<<max(a, b)<<endl; double m=1.5, n=5.6;
cout<< "较大实数:"<<max(m, n)<<endl; return 0;
}

执行结果例如以下:

类模板

类模板的一般形式例如以下:

template <class 形參名, class 形參名, ……>   class 类名

{

//类定义...

};

一但声明了类模板就能够用类模板的形參名声明类中的成员变量和成员函数,即能够在类中使用内置类型的地方都能够使用模板形參名来声明。比方:

template <class T> class A
{
public:
T a;
T b;
T hy(T c, T &d);
};

在类 A 中声明了两个类型为T的成员变量 a 和 b。还声明了一个返回类型为 T 带两个參数类型为 T 的函数 hy。

类模板对象的创建:比方一个模板类 A,则使用类模板创建对象的方法为 A<int> m;在类 A 后面跟上一个 <> 尖括号并在里面填上对应的类型。这种话类 A 中凡是用到模板形參的地方都会被 int  所取代。

当类模板有两个模板形參时创建对象的方法为 A<int, double> m;类型之间用逗号隔开。

在类模板外部定义成员函数的方法为:

template<模板形參列表> 函数返回类型 类名<模板形參名>::函数名(參数列表){函数体}

比方有两个模板形參 T1。T2 的类 A 中含有一个 void h() 函数。则定义该函数的语法为:

template<class T1, class T2> class A
{
public:
void h();
}; template<class T1,class T2> void A<T1,T2>::h()
{
// ……
}

注意:模板的声明或定义仅仅能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比方不能在 main() 函数中声明或定义一个模板。

演示样例代码例如以下:

#include <iostream>
using namespace std; template <class numtype> class Compare //类模板
{
public:
//Compare(numtype a,numtype b){x=a;y=b;}
Compare(numtype a,numtype b);
numtype max(){return (x>y)?x:y;}
numtype min(){return (x<y)? x:y;}
private:
numtype x,y;
}; template <class numtype> Compare<numtype>::Compare(numtype a,numtype b)
{
x=a;
y=b;
} int main( )
{
Compare<int>cmp1(3,7); //定义对象cmp1,用于两个整数的比較
cout << cmp1.max() << " is the Maximum" << endl;
cout << cmp1.min() << " is the Minimum" << endl << endl; Compare<float> cmp2(45.78,93.6); //定义对象cmp2。用于两个浮点数的比較
cout << cmp2.max() << " is the Maximum" <<endl;
cout << cmp2.min() << " is the Minimum" <<endl<<endl; Compare<char> cmp3('a', 'A'); //定义对象cmp3。用于两个字符的比較
cout << cmp3.max() << " is the Maximum" <<endl;
cout << cmp3.min() << " is the Minimum" <<endl; return 0;
}

执行结果例如以下:

本教程演示样例代码下载请点此处。

參考资料:

http://www.cnblogs.com/gw811

http://www.cnblogs.com/gaojun

C++入门学习——模板的更多相关文章

  1. Elasticsearch7.X 入门学习第八课笔记-----索引模板和动态模板

    原文:Elasticsearch7.X 入门学习第八课笔记-----索引模板和动态模板 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接: ...

  2. opengl入门学习

    OpenGL入门学习 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640 ...

  3. ReactJS入门学习一

    ReactJS入门学习一 阅读目录 React是什么? React如何制作组件? 理解组件属性props 理解页面中如何渲染数据的 理解从服务器端获取数据及理解state的 回到顶部 React是什么 ...

  4. OpenGL入门学习(转)

    OpenGL入门学习 http://www.cppblog.com/doing5552/archive/2009/01/08/71532.html 说起编程作图,大概还有很多人想起TC的#includ ...

  5. OpenCV入门学习笔记

    OpenCV入门学习笔记 参照OpenCV中文论坛相关文档(http://www.opencv.org.cn/) 一.简介 OpenCV(Open Source Computer Vision),开源 ...

  6. Egg入门学习(二)---理解service作用

    在上一篇文章 Egg入门学习一 中,我们简单的了解了Egg是什么东西,且能做什么,这篇文章我们首先来看看官网对Egg的整个框架的约定如下,及约定对应的目录是做什么的,来有个简单的理解,注意:我也是按照 ...

  7. OpenGL入门学习(转载)

    说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率.16色 ...

  8. JavaSE入门学习21:Java面向对象之接口(interface)(二)

    一接口实现的多态 在上一篇博文:JavaSE入门学习20:Java面向对象之接口(interface)(一)中提到了接口的实现存在多态性,那么 这一篇主要就要分析接口实现的多态. 实例一 Test.j ...

  9. 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习

    反射实现Model修改前后的内容对比   在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...

随机推荐

  1. Vue beaforeCreate时获取data中的数据

    异步获取即:通过    $this.$nextTick或者settimeout,这连dom都可以拿出来 beforeCreate() { this.$nextTick(function() { con ...

  2. 背景渐变 background-image:linear-gradient(0deg,#fff,#ccc);

    背景渐变 background-image:linear-gradient(0deg,#fff,#ccc);

  3. 对比props

    1.在组件中data返回数组对象 2.在父级作用域中写入 (1)prop传值 <btn-grp :buttons="buttons"></btn-grp> ...

  4. 笔试算法题(13):反转链表 & 左旋转字符串

    出题:反转链表(递归和非递归解法): 分析:有递归跟非递归实现,注意对原始链表头节点的处理,因为其他节点都指向下一个节点,其需要指向NULL: 解题: struct Node { int v; Nod ...

  5. C++ typedef用法小结 (转载)

    声明:本文转自charley_yang,点击此处查看原文 第一.四个用途 用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如:char* pa, pb; // ...

  6. 去掉idea中的警告

    目前我使用的两种方法 1.idea右下角有个小人,单击后选择Syntax即可 2.在setting→Editor→Inspections搜索SQL,把No data sources configure ...

  7. 简述HTTP报文请求方法和状态响应码

    1. Method 请求方法,表明客户端希望服务器对资源执行的动作: 1.1 GET 向服务器请求资源. 1.2 HEAD 和GET方法的行为类似,但服务器在响应中只返回首部,不会返回实体的主体部分. ...

  8. python爬取百度文库所有内容

    转载自 GitHub 的 Jack-Cherish 大神 基本环境配置 版本:python3 系统:Windows 相关模块: import requests import re import jso ...

  9. Matlab学习笔记(二)

    二.MATLAB基础知识 (二)数值.变量和表达式 命名规则: 变量名对大小写敏感,即区分大小写 变量名必须以字母开头,后面可以采用数字.下划线和字母,但不能使用空格.标点符号和运算符 变量名最长可以 ...

  10. table中JS选取行列

    <table border="1" align="center" style="width: 500px" id="doct ...