C++泛型編程:template模板


 

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

所謂template,是針對“一個或多個尚未明確的類型”所編寫的函數或類.

使用template時,可以顯示的或隱示的將類型當作參數來傳遞.

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

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

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

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

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

理解:

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

缺省模板參數

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)
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM