目录
1.泛型
2.函数模板
3.函数模板和重载的区别
4.函数模板实例化
5.类模板
6.模板特化
⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳⛳
1.泛型 泛型是编写与类型无关的类型代码,是代码复用的一种手段。
泛型是对面向对象的一种补充,极大的提高了代码复用率。
在c++中,泛型的实现方式主要有函数模板和类模板。
😎
2.函数模板 函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生特定类型的版本。
不是真正的函数,只是编译器生成代码的一种规则,比如传int型参数,编译器就生成一份int型的代码。
😁😁
3.函数模板和重载的区别函数模板的使用格式
template
类型名 函数名(类型名 参数){
//若传递多组参数,参数之间用,隔开
}
函数模板举例
#include
using namespace std; template T add(T left, T right) { return left + right; } int main() { cout< 🏓🏓代码验证编译器会对代码进行拷贝,然后修改其参数类型
#include
using namespace std; template I add(I left, F right) { return left + right; } int main() { cout< 🧧🧧分析:我们为定义三种类型的函数,则这三次函数调用来源于函数模板,从反汇编中看到三次函数的入口地址使不同的,所以编译器对模板进行了三次拷贝,然后推演对应参数类型。
4.函数模板实例化🧨🧨 函数重载是函数名相同,函数参数列表不同。
函数模板可以看成函数重载的进化版,它使用“占位符”作为函数的参数类型,解决了重载工作量大,代码复用率低的特点。
函数模板可以与同名函数同时存在,优先调用非模板函数(或者重载),假如再生成一份函数就会浪费资源。
下边来验证模板和函数重载,实现一个加法函数,传进去两个值,相加返回结果。
#include
using namespace std; //函数重载版本 int add(int left,int right) { return left + right; } double add(double left, double right) { return left + right; } double add(int left, double right) { return left + right; } double add(double left,int right) { return left + right; } //函数模板版本 template T add(T left, T right) { return left + right; } int main() { cout< 分析:函数重载需要考虑不同的函数类型,分情况讨论导致代码量翻倍,函数模板 就很好的解决了这个问题。
5.类模板函数模板实例化后,编译器根据实例化结果来推演实参的类型,然后根据推演的结果生成处理具体类型的参数。
隐式 实例化
在传参时未给出参数类型,让编译器自己推演,称为隐式实例化。
比如上边的栗子。
显式实例化
在传参时显式给出参数类型,不需要编译器推演,STL用的大多都是显式实例化。
栗子
#include
using namespace std; //函数模板版本 template I add(I left,I right) { return left + right; } int main() { cout< ✨🧨两个参数类型不一样时,编译器就无法推演参数类型,虽然我们也可增加参数列表解决这个问题,但是我们有更好的方法,就是在传参时显式实例化,即告诉编译器参数类型。
int main() { cout<(1, 2.2)<
🥨🥨显式实例化格式
函数名<参数类型>(参数...)
6.模板特化我们常常遇到类相同,参数类型不同的情况,这个时候类模板就发挥了作用。
🥩🥩类模板的定义格式
template
class 类模板名{ 成员函数和成员变量 }; 🍔🍔用类模板定义对象
类模板名<参数类型>对象名(参数列表);
举个例子
#include
using namespace std; //类模板 template class student { private: T age; S name; public: student(T _age,S _name) { //构造函数 age = _age; name = _name; } void homework() { //成员函数 cout << age << endl; } }; int main() { student stu1(20,"王小明"); //模板实例化对象 stu1.homework(); return 0; } 🥚🥚分析:以上我们演示了类模板的使用方法,需要注意的是,函数模板可以隐式实例化,但是类模板只能显式实例化。
🌭🌭 模板特化是指某些情况下,模板会出现错误的情况,我们就需要对这种情况进行特殊化处理。
模板特化格式
template<> 实际类型名 函数名(要特化的实际类型){ }
🥗🥗特化分为全特化和偏特化
全特化:全部参数重新给出
偏特化:部分参数给出,也是在全特化基础上进一步限制
🥟🥟举一个需要模板特化的栗子
#include
using namespace std; template int compare(T left,T right) { if (left > right) { return 1; } else if (left < right) { return -1; } else { return 0; } } int main() { const char* a = "bcdef"; const char* b = "abcde"; cout< 🌮🌮函数模板特化版本(全特化)
#include
using namespace std; template int compare(T left,T right) { if (left > right) { return 1; } else if (left < right) { return -1; } else { return 0; } } template<> int compare(const char* left, const char* right) { while (*left != '\0') { if (*left > *right) { return 1; } else if (*left < *right) { return -1; } else { return 0; } left++; right++; } } int main() { const char* a = "bcdef"; const char* b = "abcde"; cout< 🌮🌮注意:一般不用有问题特化,哪种类型错误就直接写一个普通函数,因为编译器优先调用自定义函数,然后是函数模板。
好啦,今天分享又告一段落了,下次见!!💗💗💗
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)