经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C++学习之函数模板的使用详解
来源:jb51  时间:2023/3/3 8:50:20  对本文有异议

C++函数模板

  1. template<typename T>
  2. void Swap(T &a ,T &b)
  3. {
  4. T temp;
  5. temp = a;
  6. a = b;
  7. b = temp;
  8. }

在使用模板函数时,编译器根据实际的类型生成相应的函数定义。

重载的模板

并非所有的类型都使用相同的算法,可以像重载常规函数那样重载模板函数定义。

  1. template<typename T>
  2. void Swap(T &a ,T &b); //#1
  3.  
  4. template<typename T>
  5. void Swap(T *a ,T *b,int n);//#2 最后一个参数是具体类型
  6.  
  7. int main()
  8. {
  9. int i =10,j=20;
  10. Swap(i,j);//使用#1
  11. const int Lim = 8;
  12. int d1[Lim]={0,1,2,3,4,5,6,7};
  13. int d2[Lim]={7,6,5,4,3,2,1,0};
  14. Swap(d1,d2,Lim);//使用#2
  15. }
  16. template<typename T>
  17. void Swap(T &a ,T &b)
  18. {
  19. T temp;
  20. temp = a;
  21. a = b;
  22. b = temp;
  23. }
  24.  
  25. template<typename T>
  26. void Swap(T *a ,T *b,int n)
  27. {
  28. T temp;
  29. for(int i=0;i<n;i++)
  30. {
  31. temp =a[i];
  32. a[i]=b[i];
  33. b[i]=temp;
  34. }
  35. }

模板局限性

某些时候,类型T的相应操作只适用于数组,如果T为结构体则模板函数便不成立

同样,如if(a>b),如果T为结构,则>便不成立

解决方案:

  • 重载运算符号
  • 为特定类型提供具体化模板定义

显示具体化

当编译器找到与函数调用匹配的具体化定义时,将使用该定义,不再寻找模板。

  • 对于给定的函数名,可以有非模板函数、模板函数和显示具体化模板函数以及各自的重载版本。
  • 显示具体化的原型和定义以template<>开头,并通过名称来指出类型
  • 调用顺序是:非模板函数>具体化模板函数>模板函数
  1. void Swap(job& ,job&);
  2.  
  3. template <typename T>
  4. void Swap(T&,T&);
  5.  
  6. template<> void Swap<job>(job& ,job&);//显示具体化
  7. //Swap<job>中<job>是可选的,因为函数的参数类型表明,这是job的一个具体化,所以也可以这样写:
  8. template<> void Swap(job& ,job&);

实例化和具体化

注意:函数模板并不会生成函数定义,他只是生成一个用于生成函数定义的方案,编译器使用模板为特定的类型生成函数定义时,得到的是模板实例。

  1. template<typename T>
  2. void Swap(T &a ,T &b);
  3.  
  4. int a =10,b=20;
  5. Swap(a,b);//因为提供了int类型的参数,所以自动生成了int类型的模板实例。这样是==隐式实例化==
  6. //也可以直接命令编译器创建特定的实例
  7. //显示实例化
  8. template void Swap<int>(int &,int &);//使用Swap()模板生成int类型的函数定义
  9.  
  10. //显示具体化
  11. template<> void Swap<int>(int& ,int&);
  12. template<> void Swap(int& ,int&);
  13. //区别在于:具体化是不使用Swap()模板函数生成函数定义,而是使用专门为int类型显示定义的函数定义
  14. //简单的理解,具体化是对函数的声明,而实例化是对模板函数的使用
  1. template<typename T>
  2. T Add(T a,T b)
  3. {
  4. return a+b;
  5. }
  6.  
  7. int m=6;
  8. double x=10.5;
  9. Add<double>(x,m); //与Add(x,m)不匹配,因为一个是int一个是double
  10. //通过Add<double>实例化,可强制将m转为double
  11.  
  12. //但是同样的对Swap便不能成功,因为Swap中使用的是引用类型
  13. Swap<double>(m,x);//double& 不能指向int
  1. //使用案例
  2. template <typename T>
  3. void Swap(T &,T &);
  4.  
  5. template<> void Swap<job>(job&,job&);//具体化
  6. int mian()
  7. {
  8. template void Swap<char>(char& ,char&);
  9. short a,b;
  10. Swap(a,b);//隐式实例化
  11. job n,m;
  12. Swap(n,m);//显示具体化
  13. char g,h;
  14. Swap(g,h);//显示实例化
  15. }

模板函数类型的确定

  1. template<class T1,class T2>
  2. void fun(T1 x,T2 y)
  3. {
  4. ?type? s=x+y; //因为是模板函数,此时?type?类型不确定
  5. }

C++11增加decltype关键字

  1. template<class T1,class T2>
  2. void fun(T1 x,T2 y)
  3. {
  4. decltype(x+y) s=x+y; //s类型与x+y的类型一致
  5. }

使用decltype(expression) var 的步骤:

1.如果expression没有用括号括起来,则var与expression类型相同,包括const等限定符

  1. double x =5.5;
  2. double& z =x;
  3. const double* pd;
  4. decltype(x) w; //w为double类型
  5. decltype(z) u; //u为double& 类型
  6. decltype(pd) v; //v为const double* 类型

2.如果expression是一个函数调用,则var与返回值类型相同。并不会实际调用函数,编译器通过查看原型来确定返回值类型

3.如果expression是一个左值,则var为指向其类型的引用。常见的情况如下:

  1. double x = 4.5;
  2. decltype((x)) r = x;//r是double&类型
  3. decltype(x) r = x;//r是double类型
  4.  
  5. //括号不会改变expression的值和左值性
  6. //可理解为加括号仅仅是decltype声明引用的一种方式

4.如果前3条都不满足,则var与expression类型相同

  1. int j=3;
  2. int &k=j;
  3. int &n=j;
  4.  
  5. decltype(j+6) x; //x是int
  6. decltype(k+n) y;//y是int ,虽然k和n是引用,但是k+n不是引用是2个int的和

如果多次声明,可以结合typedefdecltype

  1. typedef decltype(x+y) xytype;
  2. xytype z = x+y;
  3. xytype arr[10];

但是某些需定义返回值类型的函数模板任然不能得到解决,如:

  1. template<class T1,class T2>
  2. ?type? fun(T1 x,T2 y) //此时无法确定类型
  3. {
  4. return x+y;
  5. }

C++新增语法auto h(int x,float y) -> double,这称为后置返回类型,auto是一个占位符

  1. template<class T1,class T2>
  2. auto fun(T1 x,T2 y)->decltype(x+y) //后置类型使用decltype
  3. {
  4. return x+y;
  5. }

到此这篇关于C++学习之函数模板的使用详解的文章就介绍到这了,更多相关C++函数模板内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号