【C++】模版-初阶

目录

泛型编程--模版

函数模版

类模版


泛型编程--模版

函数模版

如何实现一个通用的交换函数呢?

 void Swap(int& left, int& right)
 {
     int temp = left;
     left = right;
     right = temp;
 }
 void Swap(double& left, double& right)
 {
     double temp = left;
     left = right;
     right = temp;
 }
 void Swap(char& left, char& right)
 {
     char temp = left;
     left = right;
     right = temp;
 } 
 ......

使用函数重载虽然可以实现,但是有一下几个不好的地方:

  1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函 数

  2. 代码的可维护性比较低,一个出错可能所有的重载均出错 那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?

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

函数模板格式:

template<typename T1, typename T2,......,typename Tn>

用class也一样:

template <class T>

 template <class T>
 void Swap(T &x, T &y)
 {
     T tmp = x;
     x = y;
     y = tmp;
 }
 ​
 int main()
 {
     int a=1,b=2;
     Swap(a,b);
     cout<<a<<" "<<b<<endl;
 ​
     double aa=1.1,bb=2.1;
     Swap(aa,bb);
     cout<<aa<<" "<<bb<<endl;
 ​
 ​
     return 0;
 }

当然 虽然提供了模版,但在使用时,int型与double型调用的函数都是不同的

函数模板的原理:

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

类型推演(实例化)

若在使用模版的同时,自己写出了有具体类型的相关函数,编译器会优先调用自己实现的函数:

 template <class T>
 void Swap(T &x, T &y)
 {
     T tmp = x;
     x = y;
     y = tmp;
 }
 ​
 void Swap(double &x, double &y)
 {
     double tmp = x;
     x = y;
     y = tmp;
 }

函数模板的实例化:

用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。

1.隐式实例化:让编译器根据实参推演模板参数的实际类型:

 template <class T>
 T Add(const T &left, const T &right)
 {
     return left + right;
 }
 int main()
 {
     int a1 = 10, a2 = 20;
     double d1 = 10.0, d2 = 20.0;
     Add(a1, a2);
     Add(d1, d2);
     /*
     该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型 通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T, 编译器无法确定此处到底该将T确定为int 或者 double类型而报错
       注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅
          Add(a1, d1);
         */
     // 此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化
     Add(a, (int)d);
     return 0;
 }

2.显式实例化:在函数名后的<>中指定模板参数的实际类型

 template <class Z>
 Z Add(const Z &left, const Z &right)
 {
     return left + right;
 }
 ​
 int main()
 {
     int a1 = 10, a2 = 20;
     double d1 = 10.1, d2 = 22.2;
     cout << Add(a1, a2) << endl;
     cout << Add<int>(a1, d2) << endl;
     cout << Add<double>(d1, a2) << endl;
     cout << Add(d1, d2) << endl;
 ​
     return 0;
 }

如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

类模版

类模板的定义格式:

 template<class T1, class T2, ..., class Tn> 
 class 类模板名
 {
     // 类内成员定义 
 };
 template <class T>
 class Stack
 {
 private:
     T *_a;
     size_t _top;
     size_t _capaicty;
 ​
 public:
     Stack(int capaicty = 4)
     {
         _a = new T[capaicty];
         _top = 0;
         _capaicty = capaicty;
     }
     ~Stack()
     {
         delete[] _a;
         _capaicty = _top = 0;
     }
 };
 ​
 int main()
 {
     //类只能 显示实例化
     Stack <int>st1;
     Stack <double>st2;
 ​
     return 0;
 }

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值