C++泛型編程:template模板

 

泛型編程就是以獨立於任何特定類型的方式編寫代碼,而模板是C++泛型編程的基礎.編程

所謂template,是針對「一個或多個還沒有明確的類型」所編寫的函數或類.函數

使用template時,能夠顯示的或隱示的將類型看成參數來傳遞.ui

下面是一個典型的例子,傳回兩數中的較大者:this

template<class T>
inline const T& MAX(const T& a,const T& b)
{
   return a>b?a:b;
}

在這裏,第一行將T定義爲任意數據類型,於函數被調用時由調用者指定.spa

這個類型有關鍵字class引導,也可用typename引導,typename其實比class更直觀.指針

(須要注意的是,若是用到了嵌套依賴類型,則必需要用到typename).code

理解:對象

  第一行template<class T>告訴編譯器:我在這兒定義了一個可變類型T,調用者使用什麼類型你就怎麼編譯吧!blog

缺省模板參數get

template class能夠有缺省參數,例如一下聲明,容許你使用一個或多個template來聲明MyClass對象:

template<class T,class container=vector<T> >
class MyClass
{
public:
     MyClass(){}
     ~MyClass(){}
protected:
private:
};

若是隻傳遞一個參數,那麼缺省參數可做爲第二參數使用:

MyClass<int> x1; // equivalent to:
MyClass<int,vector<int> > x2;

注意:template缺省參數根據前一個(或前一些)參數而定義。這也就意味着若是參數傳遞列表中某個參數是缺省參數,那麼後面的全部參數都應該是缺省參數.

關鍵字typename

關鍵字typename被用來作爲類型以前的標識符號。考慮下面例子:

template<class SubType>
struct BaseType
{
     SubType a;
};

template <class T>
class MyClass1
{
     typename T::SubType *ptr;
     // ...
};

這裏,typename指出SubType是class T中定義的一個類型,所以ptr是一個指向T::SubType的指針.

若是沒有typename,SubType將會被當成一個static成員,因而:

T::SubType * ptr;

會被解釋爲類型T中的兩個子成員SubType和ptr的乘積.

成員模板

class成員函數能夠是個template,可是這樣的成員template類型既不能是virtual,也不能有缺省參數,例如:

class MyClass
{
     //...
     template<class T>
     void f(T);
};

在這裏,MyClass::f聲明瞭一個成員函數,適用於任何類型參數.

這個特性經常使用來爲template class中的成員提供自動類型轉換,例以下面的例子中,assign()的參數x,其類型必須和調用端所提供的對象的類型徹底吻合:

template<class T>
class MyClass
{
public:
     MyClass();
     ~MyClass();
     void assign(const MyClass<T>& x) // x must have same type as *this
     {
           value=x.value;
     }
     // ...
protected:
private:
     T value;
};

若是使用了兩個類型,即便兩個類型之間能夠自動轉換,也會出錯:

void fun()
{
     MyClass<double> d;
     MyClass<int> i;

     d.assign(d); // OK
     d.assign(i); // ERROR: i is MyClass<int> but MyClass<double> is required
}

理解:

  對於一個template class中的template成員,遵循「先入爲主」,若是第一次指定了類型,那麼後面都要和第一次保持一致.

但若是要指定兩個不一樣類型的類成員變量怎麼辦呢?

方法很簡單,咱們將成員變量在使用一個和class不一樣的template類型就行:

template<class T>
class MyClass
{
public:
     MyClass();
     ~MyClass();
     template<class X> // member template
     void assign(const MyClass<X>& x) // allow different template types
     {
           value = x.getValu();
     }
     T getValue() const
     {
           return value;
     }
     // ...
protected:
private:
     T value;
};

void fun()
{
     MyClass<double> d;
     MyClass<int> i;
     
     d.assign(d); // OK
     i.assign(i); // OK (int is assigned to double)
}
相關文章
相關標籤/搜索