泛函编程—模板函数_类模板
函数业务逻辑一样,只是函数参数类型不同
函数模板的本质:类型参数化——泛型编程
语法:
template <typename T> template <class T1,class T2>多个参数类型 类型 函数名(形式参数表) {语句序列; }
函数模板基础:
template是告诉C++编译器,开始泛型编程,看到T,不要随便报错
template <typename T>//一个模板 void myswap(T& a, T& b) {T c;c = a;a = b; } //调用时,显式说明类型myswap<int>(x,y);myswap<char>(x,y); //自动类型推倒,尽量不要用myswap(x,y);template <typename T1, typename T2>//两个模板,定义了一定要用 void myswap(T1& a, T2& b) {}
在使用模板时,遇到修改模板里面内容,需要清除原有方案,重新编译。
函数模板遇上函数重载:
//函数模板不允许自动类型转化,严格的类型匹配
//普通函数能够进行自动类型转化,在不失精度的前提下
1、函数模板可以像普通函数一样被重载
2、C++编译器优先考虑普通函数
3、如果函数模板可以产生一个更好的匹配,那么选择模板(比如在使用普通函数导致精度缺失的时候)
4、可以通过空模板实参列表的语法限定编译器只通过模板匹配
template <typename T>//一个模板 void myswap(T& a, T& b) {T c;c = a;a = b; } //一个普通函数 void myswap(int& a, char& b) {int c;c = a;a = b; } int a = 10; char c = 'c'; myswap(a,c) //调用普通函数 myswap(c,a) //调用普通函数,进行隐形类型转换 myswap(a,a) //调用模板函数,严格的类型匹配,不会进行类型转换;但是普通函数如果也有两个int形参时,优先普通函数,看下一个例子 //模板函数重载
int max(int a, int b) {return a>b?a:b; } template<typename T> T max(T a, T b) {return a>b?a:b; } template<typename T> T max(T a, T b, T c) {return max(max(a,b), c); }int a = 1; int b = 2; max(a,b); //函数模板和普通函数都满足调用时,优先普通函数 max<>(a,b);//显示使用函数模板方法,则使用<>空的类型参数化列表 max(3.0,4.0);//类型一致,可以使用模板。且使用普通函数,失真,则调用函数模板 max(3.0,4.0,5.0);//函数模板可以重载 max('a',100); //类型不一致,不能用函数模板,调用普通函数进行隐式类型转换
函数模板机制结论:
编译器并不是把函数模板处理成能够处理任意类的函数
函数模板通过具体类型产生不同的函数
编译器会对函数模板进行二次编译:
在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译
类模板:
解决问题:多个类功能一致,数据类型不同。
类模板用于实现类所需数据的类型参数化;
类模板在表示数组、表、图等数据结构显得特别重要;
实现 数据结构 与 算法的分离,类模板可以使 链表类型存不同数据类型数据
类模板的定义和使用:
template <typename T> class A { public:A(T a=0){this->a = a;} public:void printA(){cout << "a: " << a << endl;} protected:T a; }int main() {A<int> a1(10); //模板类是抽象的,需要进行类型具体化a1.printA();system("pause");return 0; }
类模板做函数参数:
void useA(A<int>& b) //C++编译器要求具体的参数类 {b.printA(); }useA(a1);
继承中的类模板:
一、模板类派生普通类
子模板类派生时,需要具体化模板类,C++编译器需要知道父类的数据类型具体是什么
要知道父类所占内存大小,只有数据类型固定才知道如何分配内存
class B:public A<int> { public:B(int a=10, int b=20):A<int>(a) //使用初始化参数列表,初始化父类对象,注意父类为模板类时,使用A<int>类类型具体化{this->b = b;} protected: private:int b; } B b1(1,2);
二、模板类派生模板类
template <typename T> class C:public A<T> //基类为模板类型 { public:C(T c, T a):A<T>(a) //基类为模板类型{this->c = c;} void printC() {cout << "c1: " << c << endl; } private:T c; }void main() { C<int>c1(1,2); c1.printC(); system("pause"); }
模板类的函数重载:
友元函数只用于重载 输入输出流 << 和 >>
其余使用成员函数,成员函数需要在类中声明,而<<需要在ostream类中声明,但我们在C++源码中修改很麻烦,
所以,使用友元实现。友元函数只需要在需要使用的地方的类中定义ostream为该类的友元函数就可以了。
在模板类中写友元函数和成员函数重载的方法:
1、所有函数声明实现都写在.h文件的内部就可以啦(简单)
2、声明和实现分开,但都在一个.cpp内
函数提出来的时候,参数类型、类作用域、返回值注意使用<T>
友元函数:只用于输入输出流
类内声明:friend ostream& operator<< <T> (ostream& out, Complex &c3); //友元函数声明有<T> 类外实现:template<typename T> ostream& operator<<(ostream& out, Complex<T>& c3) //友元函数是全局函数,不需要类的作用域 {}
template<typename T>
成员函数:
类内声明: Complex operator+(Complex &c2); //正常写就可以啦 类外定义:主要三要素 Complex<T> Complex<T>::operator+(Complex<T>& c2) {Complex tem(a+c2.a,b+c2.b);return tem; }
除了输入输出流使用友元函数重载,其余最好使用成员函数重载,不然处理起来很麻烦。。。
3、.h和.hpp分开,其他类使用,要包含.hpp(不是.cpp)
这个时候和情况2差不多,滥用友元函数容易出问题。
模板类中的static关键字,不同的调用类型,static关键字属于不同的类,这是由模板的实现机制决定的。
static是属于具体类的。
转载于:https://www.cnblogs.com/Lunais/p/5852367.html
泛函编程—模板函数_类模板相关推荐
- C++函数模板和模板函数、类模板和模板类
这期间有涉及到函数模板与模板函数,类模板与模板类的概念 (类似于类与类对象的区别) 注意:模板类的函数声明和实现必须都在头文件中完成,不能像普通类那样声明在.h文件中,实现在.cpp文件中. 1.函数 ...
- C++模板学习02(类模板)(类模板语法、类模板与函数模板的区别、类模板中的成员函数创建时机、类模板对象做函数参数、类模板与继承、类模板成员函数类外实现、类模板分文件编写、类模板与友元)
C++引用详情(引用的基本语法,注意事项,做函数的参数以及引用的本质,常量引用) 函数高级C++(函数的默认参数,函数的占位参数,函数重载的基本语法以及注意事项) C++类和对象-封装(属性和行为作为 ...
- 类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器
1.第一个最简单的类模板案例 #include "mainwindow.h" #include <QApplication> #include <QPush ...
- C++中模板类中的成员函数以及模板函数在类外定义
在C++中,类中的成员函数可以在类外完成定义,从而显得类中的成员函数看起来简洁明了.但是模板类里的成员函数和模板函数与普通的成员函数在类外定义不同. 先定义一个模板类以及成员函数和模板函数: 接下我们 ...
- c++模板---3(类模板碰到继承问题,类模板类外实现,类模板与友元函数)
类模板碰到继承问题 基类如果是模板类,必须让子类告诉编译器 基类中的T到底是什么类型 如果不告诉,那么无法分配内存,编译不过 利用参数列表class Child :public Base<int ...
- 模板 (函数模板语法 ,类模板与函数模板的区别,:函数模板案例,普通函数与函数模板的区别,普通函数与函数模板调用规则,模板的局限性,类模板分文件编写.cpp,Person.hpp,类模板与友元)
**01:函数模板语法: #include<iostream> using namespace std;//交换两个整型函数 void swapInt(int &a ,int &a ...
- C++(11):模板函数的默认模板参数
C++11支持在模板函数中使用默认的模板参数 #include <iostream> #include <typeinfo> using namespace std;templ ...
- java 模板函数_重温Java中的模板方法设计模式
Java 8 lambda表达式的简洁性为经典的GoF设计模式提供了新的视角.通过利用函数式编程,我们可以通过更少的耦合获得相同的好处 - 模板方法就是一个很好的例子. 经典的GoF模板方法实现 模板 ...
- 合同模板布局html,套打模板制作(合同类模板)
在制作模板前,需要了解以下几点 ① 布局表格是默认每页出现的(设置布局表格是否每页出现是不生效的),而当布局表格本身的行设置了行高自适应而产生的换页,默认为当前布局表格页还未结束,因此,这种情况产生的 ...
最新文章
- 怎么样才可批量导出word文档中的照片 不再一张一张的另存为!
- 计算机二级公共基础知识证书,计算机二级公共基础知识
- mysql 安装问题一:由于找不到MSVCR120.dll,无法继续执行代码.重新安装程序可能会解决此问题。
- GMIS 2017 大会余凯演讲:深度学习引领驾驶革命
- jquery中$each()
- 换了一个皮肤,心情也好多了
- 【报告分享】中国零售业公私域运营手册暨实施指引.pdf(附下载链接)
- linux上oracle导入mysql_linux下的oracle数据库和表空间的导入导出
- 机械的东西学的难 还是计算机的难,最难学十大工科专业 不想累成狗就别去(高薪)...
- StanfordDB class自学笔记 (14) On-Line Analytical Processing
- 【数学建模】相关性分析 - 皮尔逊相关系数 斯皮尔曼相关系数
- ansys workbench汉化教程_ARP8.1企业版安装及汉化教程 I 学之乎
- 阿里云智能巡检管家使用攻略及功能示例
- 科学与财富杂志科学与财富杂志社科学与财富编辑部2022年第27期目录
- 关于如何利用学生邮箱申请jetbrains免费全家桶
- evernote国际版不可用
- java 补齐字符串_使用String.format()格式化字符串,java自动补全自增长字符串
- 汽车制动盘的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
- GPS 轨迹处理方法
- 12月世界燕窝滋补品展|上海燕博会|冻干(即食)燕窝展谈食用燕窝
热门文章
- [deviceone开发]-do_Dialog的基本使用示例
- HokeyPokey — WWDC讲师特供XCode插件高仿版的设计与实现
- 【WIN10】程序內文件讀取與保存
- 在最长的距离二叉树结点
- {面试题2: 实现 Singleton 模式}
- linux下查看进程占用端口和端口占用进程命令
- 百度2014校园招聘笔试题(成都站,软件研发岗)——2014.09.21
- 一个项目涉及到的50个Sql语句(整理版)
- Android点击事件(click button)的四种写法
- jquery 只能输入汉字