STL與泛型編程(三)
閱讀C++ STKL源碼的基礎(chǔ)條件
1 操作符重載
operator是C++的關(guān)鍵字,它和運(yùn)算符一起使用腮鞍,表示一個(gè)運(yùn)算符函數(shù)值骇,理解時(shí)應(yīng)將operator=整體上視為一個(gè)函數(shù)名。
這是C++擴(kuò)展運(yùn)算符功能的方法移国,雖然樣子古怪雷客,但也可以理解:一方面要使運(yùn)算符的使用方法與其原來一致,另一方面擴(kuò)展其功能只能通過函數(shù)的方式(c++中,“功能”都是由函數(shù)實(shí)現(xiàn)的)。
1.1 為什么使用操作符重載蘸秘?
對(duì)于系統(tǒng)的所有操作符恨搓,一般情況下,只支持基本數(shù)據(jù)類型和標(biāo)準(zhǔn)庫中提供的class娜汁,對(duì)于用戶自己定義的class嫂易,如果想支持基本操作,比如比較大小掐禁,判斷是否相等怜械,等等,則需要用戶自己來定義關(guān)于這個(gè)操作符的具體實(shí)現(xiàn)傅事。比如缕允,判斷兩個(gè)人是否一樣大,我們默認(rèn)的規(guī)則是按照其年齡來比較蹭越,所以障本,在設(shè)計(jì)person 這個(gè)class的時(shí)候,我們需要考慮操作符==响鹃,而且驾霜,根據(jù)剛才的分析,比較的依據(jù)應(yīng)該是age买置。那么為什么叫重載呢粪糙?這是因?yàn)椋诰幾g器實(shí)現(xiàn)的時(shí)候忿项,已經(jīng)為我們提供了這個(gè)操作符的基本數(shù)據(jù)類型實(shí)現(xiàn)版本蓉冈,但是現(xiàn)在他的操作數(shù)變成了用戶定義的數(shù)據(jù)類型class城舞,所以,需要用戶自己來提供該參數(shù)版本的實(shí)現(xiàn)洒擦。
2 模板
2.1函數(shù)模板的聲明和模板函數(shù)的生成
2.1.1 函數(shù)模板的聲明
函數(shù)模板可以用來創(chuàng)建一個(gè)通用的函數(shù)椿争,以支持多種不同的形參,避免重載函數(shù)的函數(shù)體重復(fù)設(shè)計(jì)熟嫩。它的最大特點(diǎn)是把函數(shù)使用的數(shù)據(jù)類型作為參數(shù)秦踪。
函數(shù)模板的聲明形式為:
template<typename 數(shù)據(jù)類型參數(shù)標(biāo)識(shí)符>
<返回類型><函數(shù)名>(參數(shù)表)
{
函數(shù)體
}
其中,template是定義模板函數(shù)的關(guān)鍵字掸茅;template后面的尖括號(hào)不能省略椅邓;typename(或class)是聲明數(shù)據(jù)類型參數(shù)標(biāo)識(shí)符的關(guān)鍵字,用以說明它后面的標(biāo)識(shí)符是數(shù)據(jù)類型標(biāo)識(shí)符昧狮。這樣景馁,在以后定義的這個(gè)函數(shù)中,凡希望根據(jù)實(shí)參數(shù)據(jù)類型來確定數(shù)據(jù)類型的變量逗鸣,都可以用數(shù)據(jù)類型參數(shù)標(biāo)識(shí)符來說明合住,從而使這個(gè)變量可以適應(yīng)不同的數(shù)據(jù)類型。例如:
template<typename T>
T fuc(T x, int y)
{
T x;
//……
}
如果主調(diào)函數(shù)中有以下語句:
double d;
int a;
fuc(d,a);
則系統(tǒng)將用實(shí)參d的數(shù)據(jù)類型double去代替函數(shù)模板中的T生成函數(shù):
double fuc(double x,int y)
{
double x;
//……
}
函數(shù)模板只是聲明了一個(gè)函數(shù)的描述即模板撒璧,不是一個(gè)可以直接執(zhí)行的函數(shù)透葛,只有根據(jù)實(shí)際情況用實(shí)參的數(shù)據(jù)類型代替類型參數(shù)標(biāo)識(shí)符之后,才能產(chǎn)生真正的函數(shù)卿樱。
關(guān)鍵字typename也可以使用關(guān)鍵字class僚害,這時(shí)數(shù)據(jù)類型參數(shù)標(biāo)識(shí)符就可以使用所有的C++數(shù)據(jù)類型。
2.1.2 模板函數(shù)的生成
函數(shù)模板的數(shù)據(jù)類型參數(shù)標(biāo)識(shí)符實(shí)際上是一個(gè)類型形參繁调,在使用函數(shù)模板時(shí)萨蚕,要將這個(gè)形參實(shí)例化為確定的數(shù)據(jù)類型。將類型形參實(shí)例化的參數(shù)稱為模板實(shí)參蹄胰,用模板實(shí)參實(shí)例化的函數(shù)稱為模板函數(shù)岳遥。模板函數(shù)的生成就是將函數(shù)模板的類型形參實(shí)例化的過程。例如:
使用中應(yīng)注意的幾個(gè)問題:
⑴ 函數(shù)模板允許使用多個(gè)類型參數(shù)烤送,但在template定義部分的每個(gè)形參前必須有關(guān)鍵字typename或class寒随,即:
template<class 數(shù)據(jù)類型參數(shù)標(biāo)識(shí)符1,…帮坚,class 數(shù)據(jù)類型參數(shù)標(biāo)識(shí)符n>
<返回類型><函數(shù)名>(參數(shù)表)
{
函數(shù)體
}
⑵ 在template語句與函數(shù)模板定義語句<返回類型>之間不允許有別的語句妻往。如下面的聲明是錯(cuò)誤的:
template<class T>
int I;
T min(T x,T y)
{
函數(shù)體
}
⑶ 模板函數(shù)類似于重載函數(shù),但兩者有很大區(qū)別:函數(shù)重載時(shí)试和,每個(gè)函數(shù)體內(nèi)可以執(zhí)行不同的動(dòng)作讯泣,但同一個(gè)函數(shù)模板實(shí)例化后的模板函數(shù)都必須執(zhí)行相同的動(dòng)作。
2.2 類模板
如同函數(shù)模板一樣阅悍,使用類模板使用戶可以為類定義一種模式好渠,使得類中的某些數(shù)據(jù)成員昨稼、某些成員函數(shù)的參數(shù)、某些成員函數(shù)的返回值能取任意類型拳锚。類模板是對(duì)一批僅僅成員數(shù)據(jù)類型不同的類的抽象假栓,程序員只要為這一批類所組成的整個(gè)類家族創(chuàng)建一個(gè)類模板,給出一套程序代碼霍掺,就可以用來生成多種具體的類匾荆,(這類可以看作是類模板的實(shí)例),從而大大提高編程的效率杆烁。
定義類模板的一般形式是:
template <類型名 參數(shù)名1牙丽,類型名參數(shù)名2,…>
class 類名
{
類聲明體
}兔魂;
例如烤芦,template <class T>
class Smemory
{…
public:
void mput(T x);
…
}
表示定義一個(gè)名為Smemory的類模板,其中帶類型參數(shù)T析校。
在類模板的外部定義類成員函數(shù)的一般形式是:
template <類型名 參數(shù)名1构罗,類型名參數(shù)名2,…>
函數(shù)返回值類型 類名<參數(shù)名 1 參數(shù)名 2智玻,…>::成員函數(shù)名(形參表)
{
函數(shù)體
}
例如:template <class T>
void Smemory<T>::mput(T x)
{…}
表示定義一個(gè)類模板Smemory的成員函數(shù)绰播,函數(shù)名為mput,形參x的類型是T尚困,函數(shù)無返回值。
類模板是一個(gè)類家族的抽象链蕊,它只是對(duì)類的描述事甜,編譯程序不為類模板(包括成員函數(shù)定義)創(chuàng)建程序代碼,但是通過對(duì)類模板的實(shí)例化可以生成一個(gè)具體的類以及該具體類的對(duì)象滔韵。
與函數(shù)模板不同的是:函數(shù)模板的實(shí)例化是由編譯程序在處理函數(shù)調(diào)用時(shí)自動(dòng)完成的逻谦,而類模板的實(shí)例化必須由程序員在程序中顯式地指定,
其實(shí)例化的一般形式是:
類名 <數(shù)據(jù)類型 1(或數(shù)據(jù))陪蜻,數(shù)據(jù)類型 2(或數(shù)據(jù))…> 對(duì)象名
例如邦马,Smemory<int> mol;
表示將類模板Smemory的類型參數(shù)T全部替換成int 型宴卖,從而創(chuàng)建一個(gè)具體的類滋将,并生成該具體類的一個(gè)對(duì)象mol。
3 特化
模版的完全特化與偏特化
模版特化:任何針對(duì)模版參數(shù)進(jìn)一步進(jìn)行條件限制設(shè)計(jì)的特化版本症昏。 <<泛型思維>>
完全特化:針對(duì)所有的模版參數(shù)進(jìn)行特化随闽。 <<c++ primer>>
舉例如下:
template<class T,class N>
class Template{};
全特化:
template<>
class Template<int,char>{};
偏特化:
template<class T>
class Template<T,int>{};
注意:函數(shù)模版不存在偏特化,只有類模版才能偏特化
#include <iostream>
using namespace std;
template<typename T, typename N>
class Test
{
public:
Test( T i, N j ) : a(i), b(j)
{
cout<<"普通模板類"<< a <<' ' << b << endl;
}
private:
T a;
N b;
};
template<>
class Test<int , char>
{
public:
Test( int i, char j ) : a( i ), b( j )
{
cout<<"模版類全特化"<< a << ' ' << b << endl;
}
private:
int a;
char b;
};
template <typename N>
class Test<char, N>
{
public:
Test( char i, N j ):a( i ), b( j )
{
cout<<"模版類偏特化"<< a<< ' ' << b << endl;
}
private:
char a;
N b;
};
//模板函數(shù)
template<typename T1, typename T2>
void fun(T1 a , T2 b)
{
cout<<"模板函數(shù)"<<endl;
}
//模版函數(shù)全特化
template<>
void fun<int ,char >(int a, char b)
{
cout<<"模版函數(shù)全特化"<<endl;
}
//函數(shù)不存在偏特化:下面的代碼是錯(cuò)誤的
// template<typename T2>
// void fun<char,T2>(char a, T2 b)
// {
// cout<<"模版函數(shù)偏特化"<<endl;
// }