C++泛型編程----(二)模板類

模板類也是模板,必須以關鍵字template開頭,後接模板形參表。

template<class 形參1class 形參2,. . .class 形參n>
class 類名
{};


上面提到的模板參數和模板的模板參數在下一節Vector迭代器時再分析。
一、模板參數
(1)模板類型形參
類型形參由關鍵字class或typename後接說明符構成。在函數模板形參表中,二者含義相同。typename其實比class更直觀,更清楚的指明後面的名字是一個類型名(包括內置類型),而class很容易讓人聯想到類聲明或類定義。
此外,在使用嵌套依賴類型(nested depended name)時,必須用到typename關鍵字。

在類的內部可以定義類型成員。如果要在函數模板內部使用這樣的類型,必須顯示告訴編譯器這個名字是一個類型,否則編譯器無法得知它是一個類型還是一個值。默認情況下,編譯器假定這樣的名字指定(靜態)數據成員,而不是類型。所以下面這段程序,如果去掉typename關鍵字,將會出現編譯錯誤。

template <typename Parm, typename U>
Parm fcn(Parm *array, U value)
{
    typename Parm::size_type * p;
}

(2)非類型模板形參
模板形參也可以是非類型形參,在使用時非類型形參由常量表達式代替。

template <typename T, size_t N>
void array(T (&parm)[N])
{
    for (size_t i = 0; i != N; ++i)
        parm[i] = 0;
}
…
int x[42];
double y[10];
array(x); //  array(int (&)[42])
array(y); //  array(double (&)[10])

浮點數和類對象是不允許作爲非類型模板參數的。

二、類模板的特化:
1、全特化:

//普通模板函數
template <class T>
struct Vector
{
public:
    Vector();
    Vector(const T* array, size_t size);
    ~Vector();
private:
    T* _start;
    T* _finish;
    T* _endOfStorage;
};

template <class T>
Vector<T>::Vector()
: _start(0)
, _finish(0)
, _endOfStorage(0)
{
    cout << "Vector<T>" << endl;
}

template <class T>
Vector<T>::Vector(const T* array, size_t size)
:_start(new T[size])
, _finish(_start)
, _endOfStorage(_start + size)
{
    cout << "Vector<T>" << endl;
}

template <class T>
Vector<T>::~Vector()
{
    if (_start)
        delete[] _start;
    _start = _finish = _endOfStorage = 0;
}
//特化成int 型
//特化後定義成員函數不再需要模板形參
template <>
struct Vector<int>
{
public:
    Vector();
    Vector(const int* array, size_t size);
    ~Vector();
private:
    int* _start;
    int* _finish;
    int* _endOfStorage;
};

Vector<int>::Vector()
: _start(0)
, _finish(0)
, _endOfStorage(0)
{
    cout << "Vector<int>" << endl;
}

Vector<int>::Vector(const int* array, size_t size)
:_start(new int[size])
, _finish(_start)
, _endOfStorage(_start + size)
{
    cout << "Vector<int>" << endl;
}

Vector<int>::~Vector()
{
    if (_start)
        delete[] _start;
    _start = _finish = _endOfStorage = 0;
}

2、偏特化:
偏特化可以分爲兩種
(1)部分參數的局部特化
(2)對模板參數進行更進一步的具體特化,比如特化爲指針類型,或者引用類型
先來看第一種

///////////局部特化////////////////
//普通模板類
template <class T1,class T2>
class B
{
public:
    B();
private:
    T1 _b1;
    T2 _b2;
};
template <class T1, class T2>
B<T1, T2>::B()
{
    cout << "B<T1,T2>" << endl;
}

//局部特化第一個參數
template <class T2>
class B<int,T2>
{
public:
    B();
private:
    int _b1;
    T2 _b2;
};
template <class T2>
B<int, T2>::B()
{
    cout << "B<int,T2>" << endl;
}


下面是第二種偏特化:

template <class T1,class T2>
class B
{
public:
    B();
private:
    T1 _b1;
    T2 _b2;
};
template <class T1, class T2>
B<T1, T2>::B()
{
    cout << "B<T1,T2>" << endl;
}

//局部特化兩個參數爲指針類型
template <class T1, class T2>
class B<T1*, T2*>
{
public:
    B();
private:
    T1 _b1;
    T2 _b2;
    T1* _b3;
    T2* _b4;
};
template <class T1, class T2>
B<T1*, T2*>::B()
{
    cout << "B<T1*,T2*>" << endl;
}

三、模板的分離編譯

總結:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章