模板

一,什么模板

模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型
使用模板的目的就是能够让程序员编写与类型无关的代码。

二,模板分类

模板分为模板函数和模板类
(1)模板函数
格式:

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

}

栗子:

template <class T>
bool IsEqual(const T& left, const T& right)
 {
    return left == right;
  }

void test()
{
    string s1("s1");
    string s2("s2");
    cout << IsEqual(s1, s2) << endl;//参数类型为string
    cout << IsEqual(1, 1) << endl;//参数类型为int
 }

注意:编译调用模板函数时,编译器会根据传入的参数自动推演出模板形参的类型,并生成对应的代码。比如IsEqual(s1,s2)其中s1和s2是string型,这时模板函数swap中的形参T就会被string所代替,模板函数就变为swap(const string & left, const string & right)。而当IsEqual(1,1)其中1和1是int类型时,模板函数会被替换为IsEqual(const int& left, const int& right)。
注意:模板函数在编译时,不检查函数内部的语法。

模板参数匹配及显式实例化

template <class T>
bool IsEqual(const T& left, const T& right)
{
    return left == right;
}

void test()
{
    cout << IsEqual(1, 1) << endl;
    //cout << IsEqual(1, 1.2) << endl;  //参数不匹配

    cout << IsEqual<int>(1, 1.2) << endl; //显式实例化
    cout << IsEqual<double>(1, 1.2) << endl;//显式实例化

}

上述代码中IsEqual(1,1.2),其中1是int型,1.2是double型,在推演时,导致模板参数’T’不明确,所以运行出错。
,
要解决上面的问题除了显式实例化,还可以重载函数模板。

template <class T>
bool IsEqual(const T& left, const T& right)
{
    return left == right;
}

template <class T1,class T2>
bool IsEqual(const T1&left,const T2& right)
{
    return left == right;
}

void test()
{
    cout << IsEqual(1, 1) << endl;
    cout << IsEqual(1, 1.2) << endl; //参数不匹配
}

(2) 模板类
格式:

 template <class T1,class T2 ....>
 class 类名
 {

 }

栗子:

template<class T>
class Vector
{
private:
    T* _first;
    T* _finish;
    T* _endofstorage;
};

非类型的函数模板参数

template <class T, int value>
T Add (const T& x )
{
    return x + value;
}

这里的value就是非类型的模板参数

非类型的类模板参数

// 静态顺序表
//template<typename T, size_t MAX_SIZE>
template <typename T, size_t MAX_SIZE = 10> //带缺省模板参数
class Vector 
{ 
public :
    Vector();
private :
    T _array [MAX_SIZE];
    int _size ;
};

template <typename T, size_t MAX_SIZE>
Vector <T, MAX_SIZE>::Vectoer ()
    : _size(0)
{}
void Test ()
{
    Vector<int > s1;
    Vector<int , 20> s2;
}

注意:浮点型不能作为非类型的类模板参数

三,类模板特化

(1)全特化

//原模板
template <class T>
class Vector
{
    Vector()
        :_data(new T[10])
    {
        cout << "T" << endl;
    }
    ~Vector()
    {
        delete[] _data;
    }
private:
    T* _data;
};

//特化后
template <>
class Vector<int>
{
    Vector()
        :_data(new int [10])
    {
        cout << "int" << endl;
    }
    ~Vector()
    {
        delete[] _data;
    }
private:
    int* _data;
};

全特化就是将模板中的某种类型单独提取出来实现,比如说,上面将int类型单独实现。
例如实现一个Equal方法,用来比较两个参数是否相等;,在实际开发中,对于float类型或者double的参数,绝对不能直接使用“==”符号进行判断。所以,对于float或者double类型,我们需要进行特殊处理。

(2)偏特化

template <typename T1, typename T2>
class Data
{
public :
    Data()
    {
        cout << "Data<T1, T2>" << endl;
    }
private:
    T1 _d1;
    T2 _d2;
};


//局部特化第二个参数
template <typename T1>
class Data <T1, int>
{
public :
    Data()
    {
        cout << "Data<T1, int>" << endl;
    }
private:
    T1 _d1;
    int _d2;
};


// 局部特化两个参数为指针类型
template <class T1,class T2>
class Data <T1*, T2*>
{
public :
    Data()
    {
        cout << "Data<T1, int>" << endl;
    }
private:
    T1* _d1;
    T2* _d2;
};

注意:模板的全特化和偏特化都是在已定义的模板基础之上,不能单独存在。

模板的分离编译
模板最好将声明和定义放到一个文件 “xxx.h” 里面,因为,编译器编译时,将不同的文件编译生成不同的文件,而模板在编译时不进行类型检查,在运行时推演,这样会导致在链接过程中会链接不上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值