函数模板

  • 1、函数模板
    • 案例:
  • 2、用户指定T的类型
  • 3、函数模板 和 普通函数的区别
    • 案例:
    • 案例2:函数模板的调用时机
  • 4、函数模板的课堂练习
  • 5、函数模板具体化
  • 6、类模板
  • 7、类模板作为函数的参数(了解)
  • 8、类模板 派生 普通类

c++提供了函数模板(functiontemplate.)所谓函数模板,实际上是建立一个通用函 数,其函数类型和形参类型不具体制定,用一个虚拟的类型来代表。这个通用函数 就成为函数模板。凡是函数体相同的函数都可以用这个模板代替,不必定义多个函 数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板 中的虚拟类型,从而实现不同函数的功能。c++提供两种模板机制:函数模板和类 模板 类属-类型参数化,又称参数模板 总结: 模板把函数或类要处理的数据类型
参数化,表现为参数的多态性,成为类属。 模板用于表达逻辑结构相同,但具体 数据元素类型不同的数据对象的通用行为。

c++特点:封装、继承、多态
c++特点:面向对象编程、泛型编程

1、函数模板

案例:

//函数模板 template是关键字
//class 和 typename一样的
//T 系统自动推导 或 用户指定
template<typename T>
void mySwap(T &a,T &b)
{T tmp;tmp = a;a = b;b = tmp;
}
void test02()
{int data1 = 10,data2=20;cout<<"data1 = "<<data1<<", data2 = "<<data2<<endl;mySwap(data1,data2);//自动推导出T为intcout<<"data1 = "<<data1<<", data2 = "<<data2<<endl;char data3 = 'a',data4='b';cout<<"data3 = "<<data3<<", data4 = "<<data4<<endl;mySwap(data3,data4);//自动推导出T为charcout<<"data3 = "<<data3<<", data4 = "<<data4<<endl;
}
int main(int argc, char *argv[])
{test02();return 0;
}

运行结果:

2、用户指定T的类型

void test03()
{int data1 = 10,data2=20;cout<<"data1 = "<<data1<<", data2 = "<<data2<<endl;//用户显示指定 T为intmySwap<int>(data1,data2);cout<<"data1 = "<<data1<<", data2 = "<<data2<<endl;
}

3、函数模板 和 普通函数的区别

案例:

void mySwap(int &a,int &b)
{cout<<"普通函数"<<endl;int tmp;tmp = a;a = b;b = tmp;
}template<typename T>
void mySwap(T &a,T &b)
{cout<<"函数模板"<<endl;T tmp;tmp = a;a = b;b = tmp;
}
void test01()
{int data1 = 10,data2 = 20;//函数模板和普通函数 都识别  优先选择普通函数mySwap(data1,data2);//函数模板和普通函数 都识别  选择函数模板 加<>mySwap<>(data1,data2);
}

运行结果:

案例2:函数模板的调用时机

函数模板可以重载

#include <iostream>using namespace std;void mySwap(int a,int b)
{cout<<"普通函数"<<endl;
}template<typename T>
void mySwap(T a,T b)
{cout<<"函数模板"<<endl;
}
void test01()
{int a = 10;char b = 'b';//默认优先选择普通函数mySwap(a,a);//选择函数模板mySwap<>(a,a);//函数模板 的参数类型 不能自动类型转换//普通函数 的参数类型 不能自动类型转换mySwap(a,b);//选择普通函数//用户 指定T的类型mySwap<int>(a,b);//选择函数模板
}
int main(int argc, char *argv[])
{test01();return 0;
}

运行结果:

4、函数模板的课堂练习

//排序
template<typename T>
void  myPintArrayTemplate(T *arr, int len)
{int i=0;for(i=0;i<len;i++)cout<<arr[i]<<" ";cout<<endl;
}template<typename T>
void mySortArrayTemplate(T *arr, int len)
{int i=0,j=0;for(i=0;i<len-1; i++){int min = i;for(j=min+1; j<len;j++){if(arr[min] > arr[j])min = j;}if(min != i){T tmp = arr[min];arr[min] = arr[i];arr[i] = tmp;}}return;
}
int main(int argc, char *argv[])
{char str[]="hello template";int str_len = strlen(str);int arr[]={5,3,4,7,8,9,1,6,10};int arr_len = sizeof(arr)/sizeof(arr[0]);//用函数模板遍历数组myPintArrayTemplate(str, str_len);myPintArrayTemplate(arr, arr_len);//用函数模板对数组排序mySortArrayTemplate(str,str_len);mySortArrayTemplate(arr, arr_len);//用函数模板遍历数组myPintArrayTemplate(str, str_len);myPintArrayTemplate(arr, arr_len);return 0;
}

运行结果:

5、函数模板具体化

#include <iostream>using namespace std;class Person
{friend  ostream& operator<<(ostream &out, Person &ob);
public:int a;int b;
public:Person(int a,int b){this->a = a;this->b = b;cout<<"构造函数"<<endl;}~Person(){cout<<"析构函数"<<endl;}//方法2:重载>运算符 推荐bool operator>(const Person &ob){return (this->a > ob.a);}
};ostream& operator<<(ostream &out, Person &ob)
{out<<"a = "<<ob.a<<", b = "<<ob.b<<endl;return out;
}
template<typename T>
T& myMax(T &a, T &b)
{return a>b ? a:b;}
//方法1:提供函数模板 具体化
#if 0
template<> Person& myMax<Person>(Person &ob1, Person &ob2)
{return ob1.a>ob2.b ? ob1:ob2;
}
#endifvoid test01()
{int data1=10,data2=20;cout<<myMax(data1,data2)<<endl;Person ob1(10,20);Person ob2(100,200);cout<<myMax(ob1,ob2)<<endl;
}
int main(int argc, char *argv[])
{test01();return 0;
}

运行结果:

6、类模板

#include <iostream>
#include<string>
using namespace std;
//类模板
template<class T1, class T2>
class Data
{private:T1 name;T2 num;
public:Data(T1 name, T2 num){this->name = name;this->num = num;cout<<"有参构造"<<endl;}~Data(){cout<<"析构函数"<<endl;}void showData(void){cout<<"name="<<this->name<<", num="<<this->num<<endl;}
};void test01()
{//Data ob1("德玛西亚",100);//err 类模板不允许 自动推导Data<string,int> ob1("德玛西亚",100);ob1.showData();Data<int,string> ob2(200, "提莫");ob2.showData();Data<int,int> ob3(100,200);ob3.showData();Data<string,string> ob4("小炮","德玛");ob4.showData();
}
int main(int argc, char *argv[])
{test01();return 0;
}

运行结果:

7、类模板作为函数的参数(了解)

#include <iostream>
#include<string>
using namespace std;
//类模板
template<class T1, class T2>
class Data
{friend void addData(Data<string,int> &ob);
private:T1 name;T2 num;
public:Data(T1 name, T2 num){this->name = name;this->num = num;cout<<"有参构造"<<endl;}~Data(){cout<<"析构函数"<<endl;}void showData(void){cout<<"name="<<this->name<<", num="<<this->num<<endl;}
};void test01()
{//Data ob1("德玛西亚",100);//err 类模板不允许 类型推导Data<string,int> ob1("德玛西亚",100);ob1.showData();Data<int,string> ob2(200, "提莫");ob2.showData();Data<int,int> ob3(100,200);ob3.showData();Data<string,string> ob4("小炮","德玛");ob4.showData();
}void addData(Data<string,int> &ob)
{cout<<"-普通函数---"<<endl;ob.name += "_vip";ob.num += 2000;return;
}void test02()
{Data<string,int> ob("德玛西亚",18);addData(ob);ob.showData();
}
int main(int argc, char *argv[])
{test02();return 0;
}

运行结果:

8、类模板 派生 普通类

#include <iostream>
#include<string>
using namespace std;
//类模板
template<class T>
class Base{private:T num;
public:Base(T num){cout<<"有参构造"<<endl;this->num = num;}~Base(){cout<<"析构函数"<<endl;}void showNum(void){cout<<num<<endl;}
};//类模板 派生 普通类 必须给基类 指定T类型
class Son1:public Base<int>{public:Son1(int a):Base<int>(a){cout<<"Son1的构造函数"<<endl;}
};class Son2:public Base<string>
{public:Son2(string a):Base<string>(a){cout<<"Son2的构造函数"<<endl;}
};int main(int argc, char *argv[])
{Son1 ob1(100);ob1.showNum();Son2 ob2("德玛西亚");ob2.showNum();return 0;
}

运行结果:

模板的超详细的案例讲解(上)相关推荐

  1. TypeScript超详细入门教程(上)

    TypeScript超详细入门教程(上) 01 开篇词:Hello~TypeScript 01 开篇词:Hello~TypeScript 更新时间:2019-10-30 13:49:46 既然我已经踏 ...

  2. 【超详细】在Linux上远程登录遇到的若干问题及解决方法(一)

    [超详细]在Linux上远程登录遇到的若干问题及解决方法(一) 目录 文章目录 [超详细]在Linux上远程登录遇到的若干问题及解决方法(一) 目录 正文 问题一:为什么我使用**ifconfig** ...

  3. 不怕问题多,就怕不复盘,超详细复盘步骤呈上,建议收藏

    步履匆匆,从不回望自己和同行人的PM,极容易丧失前进的方向,避免丧失方向的最好方法是--复盘.所谓"磨刀不误砍柴工","复盘"就是磨砺利器的过程.又到月底了,来 ...

  4. 概要设计和详细设计模板_超详细的【免试拼】铝模板设计深化配模方案 非筑名铝模板设计...

    超详细的[免试拼]铝模板设计深化配模方案 非筑名铝模板设计 专注于免试拼的铝模板设计和设计师培训--河北非筑名铝模科技有限公司 铝模板设计深化图 铝模板设计混凝土建模模型 铝模板设计3D配模模型 知乎 ...

  5. 支持向量机(SVM)----超详细原理分析讲解

    文章目录 支持向量机(SVM) 直观的本质理解 几个基础概念 决策超平面的求解(SVM模型的推导) 最大硬间隔的寻找与公式构建 拉格朗日乘数法的应用 使用对偶问题求解 一个小例子(求解决策超平面与决策 ...

  6. Arcgis更换布局模板_超详细的ArcGIS生成格网知识汇总

    1. 概述 格网是使用建立格网图层地理处理工具(ArcGIS for Desktop Standard 许可等级)和格网定义文件创建的,格网定义文件中包含了规范中的全部详情.该文件中存储了各个格网的规 ...

  7. Python编程从入门到实践笔记(超详细的精华讲解+内有2021最新版本代码)

    编程环境的安装请见我个人博客https://tianjuewudi.gitee.io/的另两篇文章<Pycharm安装方法>及<Pycharm配置和使用教程>,下面以你能正常使 ...

  8. python入门教程(非常详细)-Python超详细入门教程(上)

    课程简介 2019千锋全新打造Python教程,深入浅出的讲解Python语言的基础语法,注重基本编程能力训练,深入解析面向对象思想,数据类型和变量.运算符.流程控制.函数.面向对象.模块和包.生成器 ...

  9. 数据分析报告,就该这么写!超详细攻略奉上

    临近年底,做数据分析的同学们都在写各种报告.按理说,写数据分析报告是数据分析师最基本的技能,人人都该会.可怕就怕,自己辛辛苦苦写完的东西没!人!看!没人看还是好的,更怕的是 在接到众多同学求助之后,今 ...

最新文章

  1. getcontentpane java_java – 为什么getcontentpane()未定义?
  2. Android 使用OpenCV的三种方式(Android Studio)
  3. 收集 | 方便实用的在线网站
  4. Android子线程更新UI的方法总结
  5. php 终止程序的方法——return、exit()、die()
  6. Linux 与 Unix 到底有什么不同?
  7. linux下启动与关闭oracle监听与实例
  8. Docker常见问题总结
  9. Linux命令之basename 命令
  10. android流量显示插件,[android]仿360状态,种流量监控桌面浮动显示
  11. screen,client,page三种确定鼠标坐标的区别和原生JS事件写法,区别于Jquery的$.on(x,y);和$.click()...
  12. java能否回文_如何使用Java查找字符串是否是回文?
  13. 小程序apkg还原_Macbook不为人知实用小技巧,学到就赚到!
  14. ProjectProfessional2003密钥
  15. advisor 2002在matlab2014a上的安装
  16. 1分钟理清楚C++类模板和模板类区别
  17. 王阳明:越是多变时,越要学会进化(附个体进化的底层心力逻辑)
  18. php rsa 模数 指数,密码:使用模数和指数生成RSA私钥
  19. Mac配置/关闭代理命令
  20. Domino蓝色多瑙河版本

热门文章

  1. python提取图片文字
  2. Android sdcard读写文件(二)
  3. python计算十年平均录取率_如何在Python中使用Pandas计算多年平均值
  4. CoreOS Linux available in China
  5. echarts饼图圆环图数据为0时字体重叠
  6. Python 万年历
  7. java sdk他edk de区别_EDK笔记——自定义IP核
  8. 回答朋友关于微信CRM系统如何使用的问题
  9. Python练习题018:a+aa+aaa+……
  10. autosar的alarm配置