• c++——初阶模板


    一. 函数模板

    1.泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。

    2.概念:函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

    3.函数模板格式:template

    (1).:typename是用来定义模板参数关键字,也可以使用class,但不能使用struct代替class,T可以自己随意起名。

    1. template<typename T>
    2. //template<class lin>
    3. void Swap( T& left, T& right)
    4. {
    5. T temp = left;
    6. left = right;
    7. right = temp;
    8. }

    (2).函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模 板就是将本来应该我们做的重复的事情交给了编译器

    (3)。在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供 调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然 后产生一份专门处理double类型的代码,对于字符类型也是如此

    4.函数模板的实例化

    (1)用不同类型的参数使用函数模板时,称为函数模板的实例化。

    (2)模板参数实例化分为:隐式实例化和显式实例化 。

    (3)隐式实例化:让编译器根据实参推演模板参数的实际类型。

    1. #include
    2. using namespace std;
    3. template<class T>
    4. T Add(const T& left, const T& right)
    5. {
    6. return left + right;
    7. }
    8. int main()
    9. {
    10. int a1 = 1, a2 = 2;
    11. double d1 = 1.2, d2 = 2.3;
    12. //强制转化
    13. cout<<Add(a1, (int)d2)<
    14. //显式实例化:用<>确定类型
    15. cout<<Add<double>(d1, a2)<
    16. return 0;
    17. }

     5.模板参数的匹配原则

    (1).一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数。

    (2).对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模 板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

    1. #include
    2. using namespace std;
    3. int Add(int left, int right)
    4. {
    5. return left + right;
    6. }
    7. // 通用加法函数
    8. template<class T1, class T2>
    9. T1 Add(T1 left, T2 right)
    10. {
    11. return left + right;
    12. }
    13. int main()
    14. {
    15. cout<<Add(1, 2)<// 与非函数模板类型完全匹配,不需要函数模板实例化
    16. cout<<Add(1, 2.3)<// 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数
    17. cout << Add(1.2, 2) << endl;//相加之后的结果于返回值的类型有关
    18. return 0;
    19. }

    二. 类模板

    1.类模板的定义格式

    1. template<class T1, class T2, ..., class Tn>
    2. class 类模板名
    3. {
    4. // 类内成员定义
    5. };

    2.类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<> 中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

    3.栈实现

    1. #include
    2. #include
    3. using namespace std;
    4. template<class T>
    5. class lin
    6. {
    7. public:
    8. lin(size_t capacity = 4)
    9. :_a(nullptr)
    10. , _size(0)
    11. , _capacity(capacity)
    12. {
    13. if (capacity > 0)
    14. {
    15. _a = new T[capacity];
    16. _size = 0;
    17. _capacity = capacity;
    18. }
    19. }
    20. ~lin()
    21. {
    22. delete[] _a;
    23. _a = nullptr;
    24. _capacity = _size = 0;
    25. }
    26. void Push(const T& data)
    27. {
    28. if (_size == _capacity)
    29. {
    30. size_t newcapacity = _capacity * 2;
    31. T* tmp = new T[newcapacity];
    32. if (_a)
    33. {
    34. memcpy(tmp, _a, sizeof(T) * _size);
    35. delete[] _a;
    36. }
    37. _a = tmp;
    38. _capacity = newcapacity;
    39. }
    40. _a[_size] = data;
    41. _size++;
    42. }
    43. void Pop()
    44. {
    45. assert(_size > 0);
    46. _size--;
    47. }
    48. bool Empty()
    49. {
    50. return _size == 0;
    51. }
    52. const T& Top()
    53. {
    54. assert(_size > 0);
    55. return _a[_size - 1];
    56. }
    57. private:
    58. T* _a;
    59. size_t _size;
    60. size_t _capacity;
    61. };
    62. int main()
    63. {
    64. lin<int> st1;
    65. st1.Push(1);
    66. st1.Push(2);
    67. st1.Push(3);
    68. st1.Push(4);
    69. st1.Push(5);
    70. while (!st1.Empty())
    71. {
    72. cout << st1.Top() << " ";
    73. st1.Pop();
    74. }
    75. cout << endl;
    76. return 0;
    77. }

  • 相关阅读:
    本地FTP YUM源报错处理
    最小生成树模板prim和kruskal
    基于Skeleton的手势识别:SAM-SLR-v2
    关于new Map( )还有哪些是你不知道的
    多GPU训练大型模型:资源分配与优化技巧 | 英伟达将推出面向中国的改良芯片HGX H20、L20 PCIe、L2 PCIe
    SuperVariMag 超导磁体系统 — SVM 系列
    计算机网络——分组延时、丢失和吞吐量
    nacos学习笔记一:nacos做注册中心和配置中心
    vue-router4之导航守卫
    基于51单片机NEC协议红外遥控发送接收仿真设计( proteus仿真+程序+原理图+报告+讲解视频)
  • 原文地址:https://blog.csdn.net/qq_64425854/article/details/126321826