农产品网站的品牌建设,建网站拿到广告,想学互联网运营从哪里入手,惠州自动seo文章目录 一.泛型编程二.函数模板1.函数模板的概念2.函数模板的格式3.函数模板的原理4.函数模板的实例化#xff08;1#xff09;隐式实例化#xff08;2#xff09;显式实例化 5.模板参数的匹配原 三.类模板1.类模板的定义格式2.类模板的实例化 前言#xff1a; 本章我们… 文章目录 一.泛型编程二.函数模板1.函数模板的概念2.函数模板的格式3.函数模板的原理4.函数模板的实例化1隐式实例化2显式实例化 5.模板参数的匹配原 三.类模板1.类模板的定义格式2.类模板的实例化 前言 本章我们将学习模板正式接触泛型编程。C相比于C语言有这么多丰富的接口与类型都源于泛型编程。本章的内容为模板初阶知识为接下来的STL学习打下坚实的基础。 一.泛型编程
如何实现一个通用的交换函数swap呢我们已经学过函数重载的使用函数重载在这种场景下作用很大:
void Swap(int a, int b)
{auto tmp a;a b;b tmp;
}void Swap(double a, double b)
{auto tmp a;a b;b tmp;
}void Swap(char a, char b)
{auto tmp a;a b;b tmp;
}
//...使用函数重载虽然可以实现但是有一下几个不好的地方
重载的函数仅仅是类型不同代码复用率比较低只要有新类型出现时就需要用户自己增加对应的函数代码的可维护性比较低一个出错可能所有的重载均出错
那能否告诉编译器一个模子让编译器根据不同的类型利用该模子来生成代码呢
这就是我们今天要讲到的模板——模板是泛型编程的基础。模板不仅适用于函数也适用于类。
二.函数模板
1.函数模板的概念
函数模板代表了一个函数家族该函数模板与类型无关在使用时被参数化根据实参类型产生函数的特定类型版本。
2.函数模板的格式
templatetypename T1, typename T2,......,typename TN
返回值类型 函数名(参数列表)
{//...函数体
}示例
templatetypename T
void Swap(T a,T b)
{auto tmp a;a b;b tmp;
}templateclass N
void Swap(N a, N b)
{auto tmp a;a b;b tmp;
}注意
typename后面的内容不一定是T可自由指定typename是用来定义模板参数关键字也可以使用class(切记不能使用struct代替class)
3.函数模板的原理
函数模板是一个描述的过程、一幅设计图、一个模板并不是真正的函数。编译器会根据模板使用特定方式产生具体类型函数。所以其实模板就是将本来应该我们做的重复的事情交给了编译器去做想想印刷术的原理。 在编译器编译阶段编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。 比如当用double类型使用函数模板时编译器通过对实参类型的推演将T确定为double类型然后产生一份专门处理double类型的代码对于字符类型也是如此。
4.函数模板的实例化
用不同类型的参数使用函数模板时称为函数模板的实例化。模板参数实例化分为隐式实例化和显式实例化。
1隐式实例化
让编译器根据实参推演模板参数的实际类型。
示例
templateclass T
T Add(T a, T b)
{return a b;
}
void Test()
{int a 10;int b 100;cout Add(a, b) endl;
}2显式实例化
在函数名后的中指定模板参数的实际类型。
错误示例:
templateclass T
T Add(T a, T b)
{return a b;
}void Test()
{int a 10;double d 3.14;cout Add(a, d) endl;
}运行结果 错误原因
因为在编译期间当编译器看到该实例化时需要推演其实参类型通过实参a将T推演为int通过实参d将T推演为double类型但模板参数列表中只有一个T编译器无法确定此处到底该将T确定为int 或者 double类型而报错。
正确的做法
①显式实例化就是在告诉编译器不用你推演了我已经指定这个类型了。
templateclass T
T Add(T a, T b)
{return a b;
}void Test()
{int a 10;double d 3.14;cout Addint(a, d) endl;
}②使用多个模板参数
templateclass T,class Y
Y Add(T a, Y b)
{return a b;
}void Test()
{int a 10;double d 3.14;cout Add(a, d) endl;
}注意
在下面情况中两次调用的swap函数不是同一个函数
templateclass N
void Swap(N a, N b)
{auto tmp a;a b;b tmp;
}
void Test()
{int a 10;int b 100;Swap(a,b);char c1 a;char c2 b;Swap(c1, c2);
}如下图所示汇编代码显然两次调用的函数并不是一个函数一个类型为Swap int 一个为Swap char 。事实上虽然我们看不见这两份函数的代码但是它们实实在在的产生了 5.模板参数的匹配原
①一个非模板函数可以和一个同名的函数模板同时存在而且该函数模板还可以被实例化为这个非模板函数。
templateclass T
T Add(T a, T b)
{return a b;
}int Add(int a, int b)
{return a b;
}void Test()
{int a 10;int b 100;cout Addint(a, b) endl;
}②对于非模板函数和同名函数模板如果其他条件都相同在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数 那么将选择模板。
templateclass T,class Y
Y Add(T a, Y b)
{cout 模板 endl;return a b;
}
int Add(int a, int b)
{cout 非模板 endl;return a b;
}
void Test()
{int a 10;int b 100;double d 3.14;cout Add(a, b) endl;//使用非模板函数cout Add(a, d) endl;//使用模板
}③模板函数不允许自动类型转换但普通函数可以进行自动类型转换
三.类模板
1.类模板的定义格式
templateclass T1, class T2, ..., class Tn
class 类模板名
{// 类内成员定义
};示例
templateclass T
class Stack
{
public://...
private:T* _a;size_t _size;size_t _capacity;
};2.类模板的实例化
类模板实例化与函数模板实例化不同类模板实例化需要在类模板名字后跟然后将实例化的类型放在中即可类模板名字不是真正的类而实例化的结果才是真正的类。
// Stack类名Stackint是类型
Stackint s1;
Stackdouble s2本文到此结束码文不易还请多多支持哦