C++ 模板

模板是泛型编程的基础,泛型编程就是编写
一些与类型无关的逻辑代码,达到代码通用复用的目的。

举个例子:我们要实现一个加法函数,但是函数的参数不确定 有可能是int 也有可能是double 还有可能是char 等等 有的人可能会想用函数重载来实现 但你想想你要把所有可能出现的类型都写一遍这未免也太麻烦了 而且万一函数逻辑有问题 那么所哟函数都可能要修改,这复用率有丶低昂。

但是用模板来解决上面问题那真的是简简单单
模板函数登场,定义一个就搞定了。

template<class T>
T add(const T& a,const T& b)
{
  return a+b;
}
int main()
{
  int i=1,j=2;
  add<i,j>;
  return 0;
}

模板分为两种形式
函数模板:针对仅参数类型不同的函数;
类模板:针对仅数据成员和成员函数类型不同的类。


函数模板的格式:
        template <class 形参名,class 形参名,......> 
        返回类型 函数名(参数列表)
   {
      函数体
   }

其中templateclass是关键字,class可以用typename代替,
<>括号中的参数叫模板形参,模板形参和函数形参很相像,模板形参不能为空。
一但声明了模板函数就可以用模板函数的形参名声明类中的成员变量和成员函数,
即可以在该函数中使用内置类型的地方都可以使用模板形参名。


例:

#include<string>
#include<iostream>
using namespace std;

template<class T>
void swap(const T& a, const T& b){
    T tmp;
    tmp = a;
    a = b;
    b = tmp;
}


int main()
{
    int a = 1, b = 2;
    swap(a, b);
    string s1 = "1111";
    string s2 = "2222";
    swap(s1, s2);
    printf("%d %d\n", a, b);
    cout << s1 << endl;
    cout << s2 << endl;
    system("pause");
    return 0;
}

这里写图片描述

这里的当你传入不同类型的参数时swap(a,b)和swap(s1,s2)
编译器在使用时就会生成不同的代码

void swap(const int&a,const int& b)
void swap(const string& s1,const string& s2)
注意:传参是必须保证参数类型的一致性否则编译不通过
int i=1;
double j = 1.1;
swap(i, j); //模板参数不匹配 编译不通过


类模板通式
template<class 形参名1,class 形参名2, ...class 形参名n>
class 类名
{ ... };
   //模板形参不能为空,一但声明了类模板就可以用类模板的形参名声明类中的
   //成员变量和成员函数,即可以在类中使用内置类型的地方都可以使用
   //模板形参名来声明
   //类模板,模板形参的类型必须在类名后的尖括号中明确指定例如 AA<int> a
   //在类模板外部定义成员函数
   template<class T> void A<T>::test(){};
   template<模板形参列表> 函数返回类型 类名<模板形参名>::函数名(参数列表){函数体}


这里写图片描述


模板参数

类型模板形参:类型形参由关见字class或typename后接说明符构成,
如>template void h(T a){};
其中T就是一个类型形参,类型形参的名字由用户自已确定。模板形参表示的是一个未知的类型。模板类型形参可作为类型说明符用在模板中的任何地方,与内置类型说明符或类类型说明符的使用方式完全相同,即可以用于指定返回类型,变量声明等。


模板的非类型形参也就是内置类型形参,如template< class T, int a > class B{};其中int a就是非类型的模板形参。

非类型模板的形参只能是整型,指针和引用,像double,String, String *这样的类型是不允许的。但是double &,double ,对象的引用或指针是正确的。

当模板的形参是整型时调用该模板时的实参必须是整型的,且在编译期间是常量
比如:template < class T, int a > class A{};
如果有int b,这时A< int, b > m;将出错,因为b不是常量,如果const int b,这时A< int, b > m;就是正确的,
因为这时b是常量。

非类型形参一般不应用于函数模板zhong


模板形参
1、可以为类模板的类型形参提供默认值,但不能为函数模板的类型形参提供默认值。函数模板和类模板都可以为模板的非类型形参提供默认值。
  2、类模板的类型形参默认值形式为:template< class T1, class T2=int > class A{};为第二个模板类型形参T2提供int型的默认值。

  3、类模板类型形参默认值和函数的默认参数一样,如果有多个类型形参则从第一个形参设定了默认值之后的所有模板形参都要设定默认值,比如templateclass A{};就是错误的,因为T1给出了默认值,而T2没有设定。

  4、在类模板的外部定义类中的成员时template 后的形参表应省略默认的形参类型。比如template < class T1, class T2=int > class A{public: void h();}; 定义方法为template < class T1,class T2 > void A< T1,T2 >::h(){}。

template < class T, template class Container >
template 表示 Container是一个模板类类型的模板形参 模板实参传什么类型 Container就是什么类型

模板参数的扩展阅读

模板小结
优点:
1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生。
2. 增强了代码的灵活性
缺点:
1. 模板让代码变得凌乱复杂,不易维护,编译代码时间变长。
2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值