c++中的函数模版
Posted ᰔᩚ. 一怀明月ꦿ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++中的函数模版相关的知识,希望对你有一定的参考价值。
🐶博主主页:@ᰔᩚ. 一怀明月ꦿ
❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++
🔥座右铭:“不要等到什么都没有了,才下定决心去做”
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
🐰函数模版
利用宏可以实现各种数据类型求最大值问题,但是宏一般简单的文本替换, 宏定义无法声明返回值的类型 。 如果宏运算的结果赋值给一个与之类型不匹配的变量,编译器并不能检查出错误#include<iostream> using namespace std; #define MAX(x,y) (x>y?x:y) int main() cout<<MAX(1,2)<<endl; cout<<MAX(1,2.1)<<endl; cout<<MAX(1.9,2.4)<<endl; return 0; 结果: 2 2.1 2.4
🌸函数模版
所谓的函数模版,实际上是建立在一个通用的函数,其函数类型和形参类型中的全部或部分类型不具体指定,用一个虚拟的类型来表示 。 这个通用的函数就是函数模版 。 凡是函数体相同的函数都可以用这个模版来代替,就不用定义多个函数了,只需在模版中定义一次即可 。在函数调用时系统会根据实参的类型来取代模版中虚拟的类型,从而实现不同的函数功能。 函数模版的定义:#include<iostream> using namespace std; 声明函数模版,其中T为类型参数 template<typename T> T Max(T a,T b)//求两数中最大值 return a>b?a:b; int main() int a=3,b=5,m; short c=7,d=8,n; double e=1.2,f=4.5,p; m=Max(a, b); n=Max(c, d); p=Max(e, f); cout<<m<<" "<<n<<" "<<p<<endl; return 0; 结果: 5 8 4.5
🌸定义函数的一般模版
template<typename T> 返回类型 函数名(形参表) 函数体; 或者 template<class T> 返回类型 函数名(形参表) 函数体;
template是定义模版的关键字,尖括号先写关键字typename(或class),后面跟一个参数类型T(T就是一个名字,也可以是其他的A,B,a...)这个类型参数实际上是一个虚拟的类型名,表示模版中出现的T是一个类型名,但是现在并未指定它是哪一种具体类型。在函数定义时用T来定义变量x和y,显然变量x和y的类型也是未确定的。要等到函数调用时根据实参的类型来确定T是什么类型。参数名T由我们自己定义,其实也可以不用T而用任何一个标识符,许多人习惯于T,而且用大写,以与实际的类型名相区别。
class和typename的作用相同,都是表示它后面的参数名代表一个潜在的内置或用户定义的类型,二者可以互换。 注意:(1)在定义模版时,不允许template语句与函数模版之间有任何其他语句。
例如:
(2)不要把这里的class与类的声明关键字class混淆在一起,虽然它们由相同的字母组成,但是含义是不同的。为了区别类与模版中的关键字class,标准C++提出了用typename作为模版参数的类型关键字,同时也支持使用class。 (3)函数模版的类型参数可以有多个,可根据实际需求确定个数,但每个类型参数都必须用关键字typename或class限定,例如template<typename T> int a;//template语句与函数模版之间有任何其他语句, T Add(T a,T b) ... ;
(4)当一个名字被声明为模版参数后,它就可以使用了,一直到模版声明或定义结束为止 。模版参数被用作一个类型指示符,可以出现在模版定义的余下部分 (5)函数模版的定义通常放到头文件中template<typename T1,typename T2,typename T3...> T1 Func(T2 a1,T3 a2,...) ...
🌸函数模版的实例化
当编译器遇到关键字template和跟随其后的函数定义时,它只是简单地知道,这个函数模版在后面的程序代码中可能会使用到。除此之外,编译器不会做额外的工作。在这个阶段,函数模版本身并不能使编译器产生任何代码,因为编译器并不知道函数模版要处理的具体数据类型。
当编译器遇到程序中对函数模版的调用时,它才会根据调用语句实际参数的具体类型,确定模版参数的数据类型,并用此类替换函数模版中的模版参数,生成能够处理该类型的函数代码。
由此可见。函数模版比使用函数重载更方便。但它只适用于函数的参数个数相同而类型不同,且函数体相同的情况下,如果参数个数不同,则不能用函数模版
🌸函数模版参数
C++在实例化函数模版的过程中,只是简单地将模版参数替换成调用实际参数类型,并以此生成模版函数,不会进行参数类型的任何转换。这种方式与普通函数处理有着很大的区别,在普通函数的调用过程中,C++会对类型不匹配的参数进行隐式转换。
例如:
#include<iostream> using namespace std; int Max1(int a,int b) return a>b?a:b; int main() cout<<"两数中最大数为:"<<endl; cout<<Max1(2, 3.8)<<endl;//因为Max1不是模版函数,而是普通的函数,虽然传入的两个数据的类型不同,一个为整形,一个为浮点型,但是函数会对传进来的实际参数进行进行隐式转换 cout<<Max1('a', 3.8)<<endl;//这里的'a'会转换为'a'的ASCII值 return 0; 结果: 两数中最大数为: 3 97
#include<iostream> using namespace std; int Max1(int a,int b) return a>b?a:b; int main() cout<<"两数中最大数为:"<<endl; cout<<Max1(2, 3.8)<<endl;//因为Max1不是模版函数,而是普通的函数,虽然传入的两个数据的类型不同,一个为整形,一个为浮点型,但是函数会对传进来的实际参数进行进行隐式转换 cout<<Max1('a', 3.8)<<endl;//这里的'a'会转换为'a'的ASCII值 return 0; 结果: 两数中最大数为: 3 97
以上代码程序编译时会报错,基模版参数不匹配。产生这种类型错误的原因就是模版实例化时,C++不会进行任何形式的参数类型的转换。上述代码,它首先调用实参的函数模版T Max(T a,T b),生成模版函数。由于Max(3.4, 2)的调用实参类型分别为double和int,而函数模版只有一个模版参数T,因此,这个调用与模版声明不匹配。
解决方法: (1)在模版调用时进行参数的强制类型的转换cout<<Max((int)(3.4), 2);
(2)通过提供"<>"里的参数类型来调用这个模版
cout<<Max<int>(3.4, 2); cout<<Max<double>(3.4, 2);
(3)指定多个模版参数
注意: 模版参数可以出现用typename或class关键字声明的类型参数除外,还可以出现确定类型参数,称为非类型参数,例如#include<iostream> using namespace std; template<typename T,typename R> T Max(T a,R b) return a>b?a:b; int main() cout<<"两数中最大数为:"<<endl; cout<<Max(3.4, 2); return 0;
template<typename T1,typename T2,typename T3,int T4> T1 Func(T1 a,T2 b T3 c,T4 d)...
🌸🌸函数模版默认实参
函数模版也可以提供默认实参🌸函数模版的重载
就像普通函数一样,也可以重载函数模版#include<iostream> using namespace std; 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 main() int a=5,b=6,c=7; cout<<"两数的最大值为:"<<endl; cout<<Max(a, b)<<endl; cout<<"三个数的最大值为:"<<endl; cout<<Max(a, b,c)<<endl; return 0; 结果: 两数的最大值为: 6 三个数的最大值为: 7
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸
C++认识模版函数
模板是泛型编程的基础。所谓泛型编程就是编写与类型无关的逻辑代码,是一种复用的方式。模板分为模板函数和模板类。
首先,我们不使用模版函数,该函数用来实现比较两个数是否相等。
bool IsEqual(int left, int right)//--->int型 { return left == right; } bool IsEqual(const string& left, const string& right)//-->string型 { return left == right; }
若直接这样实现,我们可以看出,两者不同类型我们就要实现两次,而这样的代码相似度又很高,就是说冗余的代码会使得编译器不易维护。
下面,我们来看一个模版函数,就可以避免这样的问题。
#include<iostream> using namespace std; #include<string> template <class T> bool IsEqual(const T& left, const T& right) { return left == right; } template<class T1,class T2> bool IsEqual(const T1& left,const T2& right) { return left == right; } bool IsEqual(const string& left, const string& right) { return left == right; } void Test() { string s1("s1"); string s2("s2"); cout << IsEqual(s1, s2) << endl; cout << IsEqual(1, 1) << endl; cout << IsEqual<int>(1, 1.2) << endl; cout << IsEqual<double>(1, 1.2) << endl; }
本文出自 “C语言100-200素数” 博客,请务必保留此出处http://10740184.blog.51cto.com/10730184/1750368
以上是关于c++中的函数模版的主要内容,如果未能解决你的问题,请参考以下文章