C++ 模板使用详解

模板语法

一、函数模板

通用语法:

template
返回类型 函数模板名 (形参表) {...}

特化语法:

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

二、类模板

通用语法:

template class 类模板名 {...};

   声明和实现分开:

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

特化语法:

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

  声明和实现分开:

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

类模板成员函数特化:

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

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

二、特例化

注意

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


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

#include 
using namespace std;
templateclass Com
{
public:
    Com(T a,T b):m_a(a),m_b(b){}
    int compare(void);
   {
      cout<<"m_a的类型"< m_b) return 1;
      else return 0;
   }
private:
    T m_a;
    T m_b;
};

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


int main(void)
{
    Comc3("abcd","abcde");
    cout<c4("abcd","abcde");
    cout<


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

三、模板的声明和实现

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

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

template<> int compare(const char*a,const char*b);
template<>
int compare(const char*a,const char*b)
{
        cout<<"a的类型"<0) return 1;
        else return 0;
}

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

四、其他说明

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

#include 
using namespace std;

template 
class Test
{
public:
    Test(void){
        cout<<"通用Test()"<class Test
{
public:
    Test(void){
        cout<<"特化Test()"<class Test
{
public:
    Test(void){
        cout<<"完全特化Test()"< t1; 
    Test t2; 
    Test t3; 
    return 0;
}
通用Test()
特化Test()
完全特化Test()
2、局部特例化与最优匹配:编译器优先选择针对指针的特化版本
3、局部特例化与最优匹配:编译器优先选择参数匹配程度最高的特化版本
=============================================================================================================
五、非类型参数和缺省参数    非类型形参=内置类型形参
#include 
using namespace std;
templateclass Array
{
public:
    Array(void):m_size(S){
        for(size_t i=0;ia1;
    a1.print();
    
//  size_t n;
//  cin>>n;
//  const size_t n = 1;
//  Arraya2;    // 整形数  非类型参数

    Arraya3;
    a3.print();

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


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

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

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

参数有三种情况:

1、整型或枚举类型

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

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

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

1、空指针常量

2、浮点型值

3、字符串

说明:

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

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


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

template class D>
class E{};

说明:

1、template class D 是一个模板。

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

模板参数使用说明:

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

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

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

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

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





你可能感兴趣的:(C++,c++,C++,模板)