【C++初阶】----模板初阶

[复制链接]
发表于 2025-10-3 18:27:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1.泛型函数

泛型编程:编写与范例无关的通用代码,是代码复用的一种本领。模板是泛型编程的底子。

2.函数模板

2.1函数模板的概念

函数模板代表了一个函数家属,该函数模板与范例无关,在使用时被参数化,根据实参范例产生函数的特定范例版本。
2.2函数模板格式
  1. template<typename T1,typename T2...,typename Tn>//写法1
  2. 返回值类型 函数名(参数列表)
  3. {}
  4. template<class T1,class T2... class Tn>//写法2
  5. 返回值类型 函数名(参数列表)
  6. {}
复制代码
注意:typename是用来界说模板参数关键字,也可以使用class(牢记:不能使用struct代替class)
  1. template<class T>
  2. void Swap(T& x, T& y)
  3. {
  4.         T tmp = x;
  5.         x = y;
  6.         y = tmp;
  7. }
复制代码
2.3函数模板的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体范例函数的模具。以是着实模板就是将原来应该我们做的重复的变乱交给了编译器
用函数模版天生对应的函数 -> 模版的实例化

在编译器编译阶段,对于模板函数的使用,编译器必要根据传入的实参范例来推演天生对应范例的函数以供调用。好比:当用double范例使用函数模板时,编译器通过对实参范例的推演,将T确定为double范例,然后产生一份专门处置惩罚double范例的代码,对于字符范例也是云云。
2.4函数模板的实例化

用差别范例的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。
  1. #include<iostream>
  2. using namespace std;
  3. template<class T>
  4. T Add(const T& x, const T& y)
  5. {
  6.         return x + y;
  7. }
  8. int main()
  9. {
  10.         int a1 = 1;
  11.         int b1 = 2;
  12.         double a2 = 1.1;
  13.         double b2 = 2.2;
  14.         //隐式实例化,让编译器根据实参推演模板参数的实际类型
  15.         cout << Add(a1, b1) << endl;
  16.         cout << Add(a2, b2) << endl;
  17.         //通过实参a1将T推演为int,通过实参a2将T推演为double类型,
  18.         //但模板参数列表中只有一个T
  19.         //编译器无法确定此处到底该将T确定为int 或者 double类型而报错
  20.        
  21.         //两种处理方式:1.用户自己来强制类型转换 2.使用显示实例化
  22.         cout << Add(a1, (int)a2) << endl;//强转
  23.         cout << Add<int>(a1, a2) << endl;//显式实例化
  24.         return 0;
  25. }
复制代码
2.5 模板参数的匹配原则


  • 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数
  • 对于非模板函数和同名函数模板,如果其他条件都类似,在变更时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板
  1. #include<iostream>
  2. using namespace std;
  3. template<class T>
  4. T Add(const T& x, const T& y)
  5. {
  6.         return x + y;
  7. }
  8. int Add(int x, int y)
  9. {
  10.         return x + y;
  11. }
  12. int main()
  13. {
  14.         //与非函数模板类型完全匹配,不需要函数模板实例化
  15.         Add(1, 2);
  16.         //模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数
  17.         Add(1, 2.2);
  18.         return 0;
  19. }
复制代码

  • 模板函数不允许主动范例转换,但平常函数可以举行主动范例转换

3.类模板

3.1模板的界说格式
  1. template<class T1, class T2, ..., class Tn>
  2. class 类模板名
  3. {
  4. // 类内成员定义
  5. };
复制代码
3.2类模板的实例化

类模板实例化与函数模板实例化差别,类模板实例化必要在类模板名字后跟<>,然后将实例化的范例放在<>中即可,类模板名字不是真正的类,而实例化的效果才是真正的类。
  1. // Stack是类名,Stack<int>才是类型
  2. Stack<int> st1;    // int
  3. Stack<double> st2; // double
复制代码
模版不发起声明和界说分离到两个文件.h 和.cpp会出现链接错误
  1. #include<iostream>
  2. using namespace std;
  3. template<class T>
  4. class Stack
  5. {
  6. public:
  7.         //构造
  8.         Stack(int n=4)
  9.                 :_array(new T[n])
  10.                 ,_size(0)
  11.                 ,_capacity(n)
  12.         {}
  13.         //析构
  14.         ~Stack()
  15.         {
  16.                 delete[] _array;
  17.                 _size = _capacity = 0;
  18.         }
  19.         //声明
  20.         void Push(const T& x);
  21. private:
  22.         T* _array;
  23.         size_t _size;
  24.         size_t _capacity;
  25. };
  26. //定义
  27. //每个函数模板都得定义自己的模板参数
  28. template<class T>
  29. void Stack<T>::Push(const T& x)
  30. {
  31.         //扩容
  32.         if (_size == _capacity)
  33.         {
  34.                 T* tmp = new T[_capacity * 2];
  35.                 memcpy(tmp, _array, sizeof(T) * _size);
  36.                 delete[] _array;
  37.                 _array = tmp;
  38.                 _capacity *= 2;
  39.         }
  40.         _array[_size++] = x;
  41. }
  42. int main()
  43. {
  44.         //类名<类型> 变量
  45.         Stack<int> st1;
  46.         st1.Push(1);
  47.         st1.Push(2);
  48.         st1.Push(3);
  49.         Stack<double> st2;
  50.         st2.Push(1.1);
  51.         st2.Push(2.2);
  52.         st2.Push(3.3);
  53.         return 0;
  54. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表