C++ 模板使用详解

模板语法

一、函数模板

通用语法:

template<class 类型形参1, class 类型形参2, ...>
返回类型 函数模板名 (形参表) {...}

特化语法:

template<>
返回类型 函数模板名<类型实参1, 类型实参2, ...> (形参表) {...}

二、类模板

通用语法:

template<class 类型形参1, class 类型形参2, ...> class 类模板名 {...};

   声明和实现分开:

template<class 类型形参1, class 类型形参2, ...> class 类模板名 {...};
template<class 类型形参1, class 类型形参2, ...>
返回类型 类模板名<类型形参1, 类型形参2, ...>::成员函数名 (形参表) {...}

特化语法:

template<> class 类模板名<类型实参1, 类型实参2, ...> {...};

  声明和实现分开:

    template<> class 类模板名<类型实参1, 类型实参2, ...> {...};
返回类型 类模板名<类型实参1, 类型实参2, ...>::成员函数名 (形参表) {...}

类模板成员函数特化:

template<>
返回类型 类模板名<类型实参1, 类型实参2, ...>::成员函数名 (形参表) {...}

=============================================================================================================

二、特例化

注意

c++模板机制规定 如果调用既能匹配普通函数,又能匹配模板函数,则优先匹配普通函数
                              因此,当我们模板特例化的时候,会先匹配特例化的函数。


当前的模板不能满足需要 就需要特例化 :例如出现 char*  字符串的比较 strcmp strcpy

#include <iostream>
using namespace std;
template<typename T>class Com
{
public:
    Com(T a,T b):m_a(a),m_b(b){}
    int compare(void);
   {
      cout<<"m_a的类型"<<typeid(m_a).name()<<endl;
      cout<<"m_b的类型"<<typeid(m_b).name()<<endl;
      if(m_a < m_b) return -1;
      if(m_a > m_b) return 1;
      else return 0;
   }
private:
    T m_a;
    T m_b;
};

template<>
int Com<char*>::compare(void){
    cout<<"|char*|特化函数"<<endl;
    if(strcmp(m_a,m_b)<0) return -1;
    if(strcmp(m_a,m_b)>0) return -1;
    return 0;
}


int main(void)
{
    Com<string>c3("abcd","abcde");
    cout<<c3.compare()<<endl;
    Com<char*>c4("abcd","abcde");
    cout<<c4.compare()<<endl;

    return 0;
}


=============================================================================================================

三、模板的声明和实现

类模板声明和实现分开、特例化

int compare(void);
template<typename T>
int Com<T>::compare(void)
{
        cout<<"m_a的类型"<<typeid(m_a).name()<<endl;
        cout<<"m_b的类型"<<typeid(m_b).name()<<endl;
        if(m_a < m_b) return -1;
        if(m_a > m_b) return 1;
        else return 0;
}
函数模板声明和实现
template<typename T> int compare(T a,T b);
template<typename T>
int compare(T a,T b)
{
        cout<<"a的类型"<<typeid(a).name()<<endl;
        cout<<"b的类型"<<typeid(b).name()<<endl;
        if(a < b) return -1;
        if(a > b) return 1;
        else return 0;
}
template<>
int Com<char*>::compare(void){
    cout<<"|char*|特化函数"<<endl;
    if(strcmp(m_a,m_b)<0) return -1;
    if(strcmp(m_a,m_b)>0) return -1;
    return 0;
}
函数模板特例化

template<> int compare<const char*>(const char*a,const char*b);
template<>
int compare<const char*>(const char*a,const char*b)
{
        cout<<"a的类型"<<typeid(a).name()<<endl;
        cout<<"b的类型"<<typeid(b).name()<<endl;
        if(strcmp(a,b)<0) return -1;
        if(strcmp(a,b)>0) return 1;
        else return 0;
}

=============================================================================================================

四、其他说明

1、局部特例化与最优匹配:编译器优先选择特化程度最高的版本

#include <iostream>
using namespace std;

template<typename T1,typename T2> 
class Test
{
public:
    Test(void){
        cout<<"通用Test()"<<endl;
    }   
};
template<typename T1>class Test<T1,int>
{
public:
    Test(void){
        cout<<"特化Test()"<<endl;
    }   
};
template<>class Test<int,int>
{
public:
    Test(void){
        cout<<"完全特化Test()"<<endl;
    }   
};
int main(void)
{
    Test<double,double> t1; 
    Test<string,int> t2; 
    Test<int,int> t3; 
    return 0;
}
通用Test()
特化Test()
完全特化Test()
2、局部特例化与最优匹配:编译器优先选择针对指针的特化版本
3、局部特例化与最优匹配:编译器优先选择参数匹配程度最高的特化版本
=============================================================================================================
五、非类型参数和缺省参数    非类型形参=内置类型形参
#include <iostream>
using namespace std;
template<typename T = string,size_t S=2>class Array
{
public:
    Array(void):m_size(S){
        for(size_t i=0;i<S;i++)
            m_t[i] = i;
    }   
    Array(T t[],size_t n):m_size(min(n,S)){
        for(size_t i=0;i<m_size;i++)
            m_t[i] = t[i];  
    }   
    void print(void){
        for(size_t i=0;i<m_size;i++)
            cout<<m_t[i]<<" ";
        cout<<endl;
    }   
public:
    T m_t[S];
    size_t m_size;
};
int main(void)
{
    Array<int,10>a1;
    a1.print();
    
//  size_t n;
//  cin>>n;
//  const size_t n = 1;
//  Array<int,n>a2;    // 整形数  非类型参数

    Array<int,20>a3;
    a3.print();

    string str[] = {"aa","bb","cc"};
 //   Array<string>a4(str,sizeof str/sizeof str[0]);
    Array<> a4(str,sizeof(str)/sizeof(str[0])); // 缺省参数
    a4.print();
    return 0;
}


非类型形参=内置类型形参:代表具体的一类(C++的标准数据类型的一种,如整型)

格式:由 标准数据类型 + 名字 组成

例如:template <int a, int b>,其中a和b都是非类型形参 或 如template<class T, int a>,T为类型参数,a为非类型参数

参数有三种情况:

1、整型或枚举类型

2、指针类型(包含普通对象的指针类型、函数指针类型、指向成员的指针类型)

3、引用类型(指向对象或指向函数的引用都是允许的)

有些常值不能作为有效的非类型实参,包括:

1、空指针常量

2、浮点型值

3、字符串

说明:

1、非类型形参在模板定义的内部是常量值,也就是说非类型形参在模板的内部是常量,或者说只能是右值,它们不能被取址,也不能被赋值

2、调用非类型模板形参的实参必须是一个常量表达式,或者是一个数,即它必须能在编译时计算出结果。


模板形参:一个模板作为另一个模板的参数

template<class A,class B,template<class C> class D>
class E{};

说明:

1、template<class C> class D 是一个模板。

2、定义一个模板E,其中有两个类型参数A和B,一个模板参数D。注意C有时候可以省略不写

模板参数使用说明:

1、首先要定义一个模板:用来实例化模板E的对象。

2、A和B可以是任意类型;但是D可以是程序员自己定义的,也可以是STL中的标准模板库

//首先定义一个普通的模板   
template<class T>  
class Array   
{  
   //模板Array的成员   
};  
//定义一个模板Container,参数列表:一个类型为T,另一个模板类型Seq   
template<class T, template<class> class Seq>//这里Seq前面的<>没有写参数名字   
class Container   
{  
    Seq<T> seq;  
    ... ...  
};  
注意:注意Seq模板的声明并没有带模板参数的名字,因为这里我们不会用到这个参数,所以可以省略不写. 
实例化:

Container<int, Array> container;
说明:模板第一个参数为int,第二个参数为STL中提供的模板(注意要使用实例化后的类型,因为这里参数必须是类型)

用途:这样定义一个泛化的容器,容器里所存储的对象也是泛化





  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值