C++进阶STL-模板

你的名字 2022-05-09 06:40 359阅读 0赞

模板的机制

模板并不是能处理任何类型的数据,只是它根据传入参数的类型的不同生成了不同的 函数/类 体(我们在不使用函数模板的正常操作,只不过编译器帮我们做了)。在此编译过程中,存在两次编译,一次是模板,一次是实例化的函数/类。


函数模板的定义

  1. template <class V1class V2…>// 或者 template < typename V1….> 告诉编译器 遇到变量V不要报错,可定义多个 V1 , V2……
  2. void Exchange ( V1 a , V1 b)
  3. {
  4. V1 c=a;
  5. a=b;
  6. b=c;
  7. }

函数模板的作用范围:

  只对后面第一个函数有效

函数模板的调用

  • 自动类型推导

    int a=10, b=0;
    Exchange(a,b);

  • 显示的指定类型

    Exchange(a,b);

函数模板与普通函数的区别

  • 普通函数在传参的时候可以进行类型转换。
  • 函数模板在传参的时候 参数的类型必须一致

函数模板与普通函数的优先级

  • 函数模板和普通函数同时存在且满足需求的时候,优先考虑普通函数。
  • 如果非得调用模板函数,在调用函数名后加<>。

定义类模板

  • 通常类模板的申明和定义写在同一文件,命名为.hpp,表明有类模板的文件。其他使用文件需要包含此.hpp
  • 类中每个函数将如下定义

    Template Student::Student() { }

类模板必须显示调用

Student S1(1,2);

类模板的派生

子类在派生父类的时候,必须先确定父类的类型

  1. template<class T> class Student { private: T m_name; } //情况1,父类确定好类型 class Person:public Student<int> { } //情况2,再重新定义个模板 template<class T> class Person:public Student< T > { }

友元函数

  • (1) 类前申明
    template class Student;
    template void Print(Student p);
  • (2)类中声明
    friend void Print(Student p);
  • (3)定义处
    template
    void Print(Student p)
    {
      cout << “name is :” << p.m_name << “age is:” << p.m_age << endl;
    }

重载操作符在类模板中申明为友元

  • 类前申明:
    template class Student;
    template ostrream& operator<< (ostrream& os Student &p);
  • 类的申明:
    template
    class Student
    {
      friend ostream& operator<< < T1, T2> (ostrream& os ,Student &p);
    }
  • 定义处:
    template
    ostrream& operator<< < T1, T2> (ostrream& os ,Student &p);
    {
      重载函数实现
    }

类模板中申明static变量,每个实例化的类拥有各自的static变量,不进行共享,

student.hpp

  1. template <class T> class Student { public: static int a; } template <class T> int Student< T >::a = 0; //初始化

main.cpp

  1. Student<int> p;
  2. p.a = 10;
  3. Student<char> p1;
  4. p1.a = 100;
  5. cout << "p.a :" << p.a << endl; //输出10
  6. cout << "p1.a :" << p1.a << endl; //输出100 p和p1虽然都是由模板来,但不共享

模板的例子:

  1. #include "stdafx.h"
  2. #include "iostream"
  3. using namespace std;
  4. //1.对象元素必须能够被拷贝 =操作符重载,默认拷贝构造是浅拷贝
  5. //容器是将对象拷贝一份放进去的,而不是将对象本身放进去的
  6. //拷贝中注意 深拷贝 浅拷贝的问题
  7. template <class T>
  8. class MyArray
  9. {
  10. public:
  11. MyArray(int capacity)
  12. {
  13. this->m_Capacity = capacity;
  14. this->m_Size = 0;
  15. m_pArrd = new T[capacity];
  16. }
  17. //拷贝构造
  18. MyArray(const MyArray<T>& array1)
  19. {
  20. this->m_Capacity = array1.m_Capacity;
  21. this->m_Size = array1.m_Size;
  22. this->m_pArrd = new T[array1.m_Capacity];
  23. for (int i = 0; i < array1.m_Size; i++)
  24. {
  25. this->m_pArrd[i] = array1.m_pArrd[i];
  26. }
  27. cout << "拷贝构造" << endl;
  28. }
  29. //[]重载
  30. T& operator [](int index)
  31. {
  32. return this->m_pArrd[index];
  33. }
  34. //等号操作符重载
  35. MyArray<T>& operator =(const MyArray<T>& array1)
  36. {
  37. if (this->m_pArrd != NULL)
  38. {
  39. delete []this->m_pArrd;
  40. }
  41. this->m_Capacity = array1.m_Capacity;
  42. this->m_Size = array1.m_Size;
  43. this->m_pArrd = new T[array1.m_Capacity];
  44. for (int i = 0; i < array1.m_Size; i++)
  45. {
  46. this->m_pArrd[i] = array1.m_pArrd[i];
  47. }
  48. cout << "重载操作符" << endl;
  49. return *this;
  50. }
  51. //对左值取引用
  52. void PushBack(T& var)
  53. {
  54. if (this->m_Size >= this->m_Capacity)
  55. return;
  56. else
  57. {
  58. this->m_pArrd[this->m_Size] = var;
  59. this->m_Size++;
  60. }
  61. }
  62. //对右值取引用(直接可以传数值)
  63. void PushBack(T&& var)
  64. {
  65. if (this->m_Size == this->m_Capacity)
  66. return;
  67. else
  68. {
  69. this->m_pArrd[this->m_Size] = var;
  70. this->m_Size++;
  71. }
  72. }
  73. ~MyArray()
  74. {
  75. if (this->m_pArrd != NULL)
  76. delete []this->m_pArrd;
  77. }
  78. private:
  79. int m_Capacity;
  80. int m_Size;
  81. T* m_pArrd;
  82. };
  83. int main()
  84. {
  85. MyArray <int> Array(10);
  86. int a = 1, b = 2, c = 3, d = 4;
  87. Array.PushBack(a);
  88. Array.PushBack(b);
  89. Array.PushBack(c);
  90. Array.PushBack(d);
  91. for (int i = 0; i < 4; i++)
  92. {
  93. cout << Array[i] <<" ";
  94. }
  95. cout << endl;
  96. MyArray <int> Array1(5);
  97. Array1 = Array;// 等号操作符重载
  98. Array1.PushBack(5); //右值作为引用
  99. for (int i = 0; i < 5; i++)
  100. {
  101. cout << Array1[i] << " ";
  102. }
  103. cout << endl;
  104. MyArray <int> Array2=Array1;//拷贝构造
  105. Array2[4] = 5;// []重载
  106. for (int i = 0; i < 5; i++)
  107. {
  108. cout << Array2[i] << " ";
  109. }
  110. cout << endl;
  111. return 0;
  112. }

发表评论

表情:
评论列表 (有 0 条评论,359人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++】模板

    非类型模板参数 模板参数分为类型形参与非类型形参。 类型形参:出现在模块参数列表中,跟在class或者typename之类的参数类型名称。 非类型形参:用一个常量

    相关 C++STL-模板

    模板的机制 模板并不是能处理任何类型的数据,只是它根据传入参数的类型的不同生成了不同的 函数/类 体(我们在不使用函数模板的正常操作,只不过编译器帮我们做了)。在此编译过