模板是一種源碼復(fù)用技術(shù),在某些情況下使用它可以使代碼看起來非常優(yōu)雅,著名的boost庫就是模板發(fā)揚的典范.
然而模板也存在弊端,大量使用模板可能導(dǎo)致代碼膨脹.下面介紹一種解決的方案:
我們首先看一段一般代碼:
template < typename T >
class Vector

{
public :
virtual void Say()

{
const type_info & t = typeid(T);
std::cout << " Vector< " << t.name() << " >::Hello " << std::endl;
}
} ;

// 特例化
template <>
class Vector < void *>

{
public :
virtual void Say()

{
std::cout << " Vector<void*>::Hello " << std::endl;
}
} ;

int _tmain( int argc, _TCHAR * argv[])

{
Vector < int *> pIntVec;
pIntVec.Say();
Vector < double *> pDoubleVec;
pDoubleVec.Say();
return 0 ;
}
輸出:
Vector<int *>::Hello
Vector<double *>::Hello
從這里,我們可以看出程序在運行的過程中生產(chǎn)了兩分Vector的代碼(int*和double*),盡管這里有特例化,然而類型不匹配,編譯器在編譯過程中無法定位到特例化版本.如果這個Vector被濫用,即使是一個中等規(guī)模的程序也可能耗費成兆字節(jié)的代碼控件.
我們必須尋找一種中間橋梁使編譯器在編譯過程中定位到void*的特例化版本.按照模板選擇策略,編譯器總是選擇最特例化的模板,我們可以通過一個中間的模板聯(lián)系起上面兩個版本的模板.下面看一段代碼:
template < typename T >
class Vector

{
public :
virtual void Say()

{
std::cout << " Vector::Hello " << std::endl;
}
} ;

// 特例化
template <>
class Vector < void *>

{
public :
virtual void Say()

{
std::cout << " Vector<void*>::Hello " << std::endl;
}
} ;

// 特例化
template < typename T >
class Vector < T *> : public Vector < void *>

{
} ;

int _tmain( int argc, _TCHAR * argv[])

{
Vector < int *> pIntVec;
pIntVec.Say();
Vector < double *> pDoubleVec;
pDoubleVec.Say();
return 0 ;
}
輸出:
Vector<void*>::Hello
Vector<void*>::Hello
從這里,我們可以看出程序在運行過程中全部使用Vector<void*>的版本.class Vector<T*>模板便是關(guān)鍵的環(huán)節(jié).編譯器在編譯過程中,由于class Vector<T*>比class Vector更特例化,所以遇到Vector<int*>和Vector<double*>時都選擇class Vector<T*>,而class Vector<T*>繼承Vector<void*>,一個更加特例化版本,所以編譯器不再產(chǎn)生新的模板而采用 Vector<void*>這個最特例化版本,這樣所有指針模板都?xì)w結(jié)到Vector<void*>,而class Vector<T*>為用戶提供了一個精美而且安全的界面,而Vector<void*>作為底層實現(xiàn)細(xì)節(jié)被隱藏.