当前位置:   article > 正文

c++ 模板_c++模板

c++模板

什么是模板?

模板是c++的一种特性,允许函数或者类(对象)通过泛型(generic types)的形式表现或者运行

模板可以使得函数或类在对应不同的类型(types)的时候正常工作,而无需为每一种类型分别写一份代码。

c++ 有两种类型的模板

1:函数模板(function tempalte):使用泛型参数的函数(function with generic parameters)

2:类模板(class template):使用泛型参数的类(class with generic parameters)

模板实例化

模板的声明(declaration)其实并未给出一个函数或者类的完全定义(definition),只是提供了一个函数或者类的语法框架(syntactical skeleton)

实例化是指从模板构建出一个真正的函数或者类的过程。用具体类型代替模板参数的过程叫做实例化;从而产生一个模板实例。

如果实例化一种类型,而该类型并不支持函数所使用的操作,那么就会导致一个编译错误

实例化有两种类型

1:显示实例化-在代码中明确指定要针对哪种类型进行实例化

2:隐式实例化-在首次使用时根据具体情况使用一种合适的类型进行实例化

函数模板编译(两次):

1:没有实例化之前,检查代码本身是否有语法错误。

2: 实例化期间,检查对模板代码的调用是否合法。

函数模板

什么是函数模板?

函数模板是参数化的一族函数(a famliy of functions)

通过函数模板,可以实例化一系类函数,这些函数都给予同一套模板框架,但是作用在不通类型的参数上

示例 :(针对不同的数据类型 比较两个数据的大小)

  1. #include <iostream>
  2. template <typename T> //模板参数由关键字typename(也可以使用class) 定义 定义一个函数模板 返回两个数中数值大的那一个
  3. inline T max(const T &a,const T &b)//函数有两个参数 ,类型为定义
  4. {
  5. return a>b?a:b;
  6. }
  7. int main()
  8. {
  9. int a =1;
  10. int b =2;
  11. auto ret = max<int>(a,b);
  12. std::cout<<"int ret = "<<ret<<std::endl;
  13. double da=1;
  14. double db =2;
  15. auto ret1 = max(da,db);
  16. std::cout<<"double ret1 = "<<ret1<<std::endl;
  17. return 0;
  18. }

参数推导

模板参数是由传递给模板函数的实参决定的

不允许自动类型转换:每个T必须严格匹配

  1. #include <iostream>
  2. template <typename T> //模板参数由关键字typename(也可以使用class) 定义 定义一个函数模板 返回两个数中数值大的那一个
  3. inline T max(const T &a,const T &b)//函数有两个参数 ,类型为定义
  4. {
  5. return a>b?a:b;
  6. }
  7. int main()
  8. {
  9. int a =1;
  10. double b =2.0;
  11. //auto ret = max(a,b); //error 模板只有一种参数 但是这里传入了两种类型的参数
  12. //解决办法
  13. //用static_cast 强制转换参数类型使得 参数匹配
  14. auto ret1 = max(static_cast<double>(a),b);
  15. //显示指定T的类型
  16. auto ret2 = max<double>(a,b);
  17. return 0;
  18. }

参数不匹配报错

函数模板重载

  1. #include <iostream>
  2. template <typename T> //模板参数由关键字typename(也可以使用class) 定义 定义一个函数模板 返回两个数中数值大的那一个
  3. inline T max(const T &a,const T &b)//函数有两个参数 ,类型为定义
  4. {
  5. return a>b?a:b;
  6. }
  7. #include <iostream>
  8. template <typename T>
  9. inline T max(const T &a,const T &b,const T &c)
  10. {
  11. T temp;
  12. if(a<b)
  13. {
  14. temp = b;
  15. }
  16. else
  17. {
  18. temp = a;
  19. }
  20. return temp >c?temp :c;
  21. }
  22. inline int max(const int &a,const int &b)
  23. {
  24. return a>b?a:b;
  25. }
  26. template <typename T,typename T1=double>
  27. inline T max(const T &a,const T1 &b)
  28. {
  29. std::cout<<"template <typename T,typename T1=double> "<<std::endl;
  30. return a>b?a:b;
  31. }
  32. int main()
  33. {
  34. max(1,2,3); // max(const T &a,const T &b,const T &c) max<int>
  35. max(1.0,2.3); //max(const T &a,const T &b) max<double>
  36. max('a','b'); //max(const T &a,const T &b) max<char>
  37. max(1,2); //inline int max(const int &a,const int &b)
  38. max<>(1,2); //max(const T &a,const T &b) max<int>
  39. max<int>(1,2); //max(const T &a,const T &b) max<int>
  40. max('a',2); //inline int max(const int &a,const int &b)
  41. return 0;
  42. }

类模板

与函数模板类似,类也可以通过参数泛化,从而可以构建出一族不同的类实例(对象)

类模板实参可以是某一类型或常量(仅限int或enum)

示例

  1. #include<iostream>
  2. #include<vector>
  3. /*********************************************************
  4. *T可以是任意类型
  5. *模板实参也可以是一个int或enum类型的常量 size_t实际是int类型
  6. *n是编译时定义的常量
  7. *n可以有默认值
  8. *size_t类型的成员变量可以用n初始化
  9. ***********************************************************/
  10. const std::size_t DefaultStackSize = 1024;
  11. template <typename T,std::size_t n = DefaultStackSize>
  12. class Stack
  13. {
  14. public:
  15. void Push(const T &element);
  16. int Pop(T &element);
  17. //int Top(T &element) const;
  18. private:
  19. std::vector<T> m_Members;
  20. std::size_t m_mMaxSize = n;
  21. };
  22. template <typename T,std::size_t nMaxSize>
  23. void Stack<T,nMaxSize>::Push(const T &element)
  24. {
  25. if(m_mMaxSize <= m_Members.size())
  26. {
  27. return;
  28. }
  29. m_Members.push_back(element);
  30. }
  31. template <typename T,std::size_t nMaxSize>
  32. int Stack<T,nMaxSize>::Pop(T& element)
  33. {
  34. if(m_Members.empty())
  35. {
  36. return -1;
  37. }
  38. element = m_Members.back();
  39. m_Members.pop_back();
  40. return 0;
  41. }
  42. int main()
  43. {
  44. Stack<int> stack;
  45. Stack<int,100> stack1;
  46. for(int i =0;i<100;i++)
  47. {
  48. stack.Push(i);
  49. }
  50. int i;
  51. stack.Pop(i);
  52. std::cout<<i<<std::endl;
  53. stack.Pop(i);
  54. std::cout<<i<<std::endl;
  55. return 0;
  56. }

类模板特化

允许对一个类模板的某些模板参数类型做特化

特化的作用和好处

对于某种特殊的类型,可能可以做些特别的优化或提供不同的实现

避免在实例化的时候引起一些可能不好的行为

特化一个类模板的时候也意味着需要特化其所有参数化的成员函数

示例:

  1. #include<iostream>
  2. #include<vector>
  3. /*********************************************************
  4. *T可以是任意类型
  5. *模板实参也可以是一个int或enum类型的常量 size_t实际是int类型
  6. *n是编译时定义的常量
  7. *n可以有默认值
  8. *size_t类型的成员变量可以用n初始化
  9. ***********************************************************/
  10. const std::size_t DefaultStackSize = 1024;
  11. template <typename T,std::size_t n = DefaultStackSize>
  12. class Stack
  13. {
  14. public:
  15. void Push(const T &element);
  16. int Pop(T &element);
  17. //int Top(T &element) const;
  18. private:
  19. std::vector<T> m_Members;
  20. std::size_t m_mMaxSize = n;
  21. };
  22. template <typename T,std::size_t nMaxSize>
  23. void Stack<T,nMaxSize>::Push(const T &element)
  24. {
  25. if(m_mMaxSize <= m_Members.size())
  26. {
  27. return;
  28. }
  29. m_Members.push_back(element);
  30. }
  31. template <typename T,std::size_t nMaxSize>
  32. int Stack<T,nMaxSize>::Pop(T& element)
  33. {
  34. if(m_Members.empty())
  35. {
  36. return -1;
  37. }
  38. element = m_Members.back();
  39. m_Members.pop_back();
  40. return 0;
  41. }
  42. template <>
  43. class Stack<std::string>
  44. {
  45. public:
  46. void Push(const T &element);
  47. int Pop(T &element);
  48. //int Top(T &element) const;
  49. private:
  50. std::list<string> m_Members;
  51. std::size_t m_mMaxSize;
  52. };
  53. int main()
  54. {
  55. Stack<int> stack;
  56. Stack<int,100> stack1;
  57. for(int i =0;i<100;i++)
  58. {
  59. stack.Push(i);
  60. }
  61. int i;
  62. stack.Pop(i);
  63. std::cout<<i<<std::endl;
  64. stack.Pop(i);
  65. std::cout<<i<<std::endl;
  66. return 0;
  67. }

类模板也可以偏特化 

  1. template <typename T1,typename T2>
  2. class MyClass
  3. {
  4. };
  5. //偏特化
  6. template <typename T>
  7. class MyClass<T,T>
  8. {};
  9. template <typename T1,typename T2>
  10. class MyClass<T1*,T2*>
  11. {};
  12. template <typename T>
  13. class MyClass<T,int>
  14. {};

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/576720
推荐阅读
相关标签
  

闽ICP备14008679号