模板類類模板
時間:2023-02-19 12:40:02 | 來源:營銷百科
時間:2023-02-19 12:40:02 來源:營銷百科
模板類類模板:類模板(class templates)可以使用類模板創(chuàng)建對一個類型進行操作的類家族。
template class T, int i // template模板參數(shù)表
class TempClass //class 類名TempClass
{public:
TempClass(void);
~TempClass( void );
int MemberSet( T a, int b );
private:
T Tarray;
int arraysize;
};
在這個例子中,模板類使用了兩個參數(shù),一個數(shù)據(jù)類型參數(shù)T和一個整型i,T參數(shù)可以傳遞一個類型,包括結(jié)構(gòu)和類,i參數(shù)必須傳遞一個整數(shù),因為I在編譯時是一個常數(shù),你可以使用一個標準 數(shù)組聲明來定義一個長度為i的成員數(shù)組模板與宏的比較(Templates vs. Macros)在很多方面,模板類似預處理宏,用給定的類型代替模板的 變量。然而,模板和宏有很大的區(qū)別:
宏:
#define min(i, j) (((i) (j)) ? (i) : (j))
模板:
templateclass T
T min (T i, T j)
{ return ((i j) ? i : j) }
使用宏會帶來如下問題:
編譯器沒有辦法檢查宏的參數(shù)的類型是否一致。宏的定義中缺少特定類型的檢查。
參數(shù)i和j被被調(diào)用了2次。例如,如果任一個參數(shù)有增量,增量會被加兩次。
因為宏被預處理 程序編譯, 編譯器 錯誤信息會指向編譯處的宏,而不是 宏定義本身。而且,在編譯階段宏會在編譯表中顯露出來。
模板和空 指針的比較(Templates VS. Void Pointers)
現(xiàn)在很多用空 指針實現(xiàn)的函數(shù)可以用模板來實現(xiàn)。空 指針經(jīng)常被用來允許函數(shù)處理未知類型的數(shù)據(jù)。當使用空指針時, 編譯器不能區(qū)分類型,所以不能處理類型檢查或類型行為如使用該類型的操作符、 操作符重載或構(gòu)造和析構(gòu)。
使用模板,你可以創(chuàng)建處理特定類型的數(shù)據(jù)的函數(shù)和類。類型在模板定義里看起來是抽象的。但是,在 編譯時間 編譯器為每一個指定的類型創(chuàng)建了這個函數(shù)的一個單獨版本。這使得 編譯器可以使用類和函數(shù)如同他們使用的是指定的類型。模板也可以使代碼更簡潔,因為你不必為符合類型如結(jié)構(gòu)類型創(chuàng)建特殊的程序。
模板和集合類(Templates and Collection Classes)
模板是實現(xiàn)集合類的一個好方法。第四版及更高版本的Microsoft Foundation Class Library使用模板實現(xiàn)了六個集合類: CArray, CMap, CList, CTypedPtrArray, CtypedPtrList和 CtypedPtrMap。
MyStack集合類是一個簡單的 堆棧的實現(xiàn)。這里有兩個模板參數(shù),T和i,指定 堆棧中的元素類型和堆棧中項數(shù)的最大值。push 和 pop成員函數(shù)添加和刪除 堆棧中的項,并在堆棧底部增加。
template class T, int i class MyStack
{
T StackBuffer[i];
int cItems;
public:
void MyStack( void ) : cItems( i ) {};
void push( const T item ); T pop( void );
};
template class T, int i void MyStack T, i ::push( const T item )
{
if( cItems 0 ) StackBuffer[--cItems] = item;
else throw 'Stack overflow error.';
return;
}
template class T, int i T MyStack T, i ::pop( void )
{
if( cItems i )
return StackBuffer[cItems ];
else throw 'Stack underflow error.';
}
模板和 智能指針(Templates and Smart Pointers)
C 允許你創(chuàng)建' 智能指針'('smart pointer')類囊括指針和 重載指針操作符來為指針操作增加新的功能。模板允許你創(chuàng)建普通包裝來囊括幾乎所有類型的 指針。
如下的代碼概括了一個簡單的計數(shù)垃圾收集者參考。模板類PtrT為任何從RefCount繼承的類實現(xiàn)了一個垃圾收集 指針。
#include stdio.h
#define TRACE printf
class RefCount
{
int crefs;
public:
RefCount(void) { crefs = 0; }
~RefCount() { TRACE('goodbye(%d)n', crefs);}
void upcount(void)
{
crefs;
TRACE('up to %dn', crefs);
}
void downcount(void)
{
if (--crefs == 0) { delete this; }
else TRACE('downto %dn', crefs);
}
};
class Sample : public RefCount
{
public:
void doSomething(void) { TRACE('Did somethingn');}
};
template class T class Ptr
{
T* p;public: Ptr(T* p_) : p(p_) { p-upcount(); }
~Ptr(void) { p-downcount(); }
operator T*(void) { return p; }
T operator*(void) { return *p; }
T* operator-(void) { return p; }
Ptr operator=(PtrT p_) {return operator=((T *) p_);}
Ptr operator=(T* p_) { p-downcount(); p = p_; p-upcount(); return *this; }
};
int main()
{
PtrSample p = new Sample;
// sample #1 PtrSample p2 = new Sample;
// sample #2 p = p2;
// #1 will have 0 crefs, so it is destroyed;
// #2 will have 2 crefs. p-doSomething();
return 0;
// As p2 and p go out of scope, their destructors call
// downcount. The cref variable of #2 goes to 0, so #2 is
// destroyed
}
類RefCount 和 PtrT共同為任何一個從RefCount繼承的能夠提供整數(shù)的類的每一個實例提供了一個簡單的垃圾收集解決方案。注意使用一個參數(shù)類如PtrT代替多個一般類如Ptr的主要好處在于這種形式是完全的 類型安全的。前面的代碼保證PtrT可以被用在幾乎任何T* 使用的地方;相反,一個普通類Ptr只能提供到void*固有的轉(zhuǎn)換。
例如,考慮一個用來創(chuàng)建和處理文件垃圾收集的類,符號、字符串等等。根據(jù)類模板PtrT,編譯器可以創(chuàng)建模板類PtrFile,PtrSymbol, PtrString等等,和它們的成員函數(shù):PtrFile::~Ptr(), PtrFile::operator File*(), PtrString::~Ptr(), PtrString::operator String*()等等。