這兩天寫(xiě)代碼,遇到這么一個(gè)模板決議的問(wèn)題:
有一個(gè)類 A,其中有兩個(gè)數(shù)據(jù)成員(方便起見(jiàn)都是 public )。為了從其它部分(比如文件)讀入數(shù)據(jù),我為 A 類重載了輸入流操作符。代碼如下所示:
程序1

typedef struct tagA
{
UINT32 biSize;
UINT32 biCount;
} A;
template <typename DataStream>
DataStream& operator>>(DataStream& a_data, A& a_fileHeader)

{
a_data>>a_fileHeader.biSize>>a_fileHeader.biCount;
return a_data;
}
一般使用標(biāo)準(zhǔn)IO流的話,這樣做至少在編譯上是沒(méi)有問(wèn)題的(讀二進(jìn)制文件不行,后有補(bǔ)充)。
在我的程序中,我目前只是測(cè)試時(shí)用文件讀取,到后期,肯定會(huì)換成其它形式(可能是直接大塊類似的數(shù)據(jù)整在一起,放在內(nèi)存中之類),所以我打算為數(shù)據(jù)源寫(xiě)一個(gè)包裝類,在目前的階段,直接轉(zhuǎn)到標(biāo)準(zhǔn)IO文件讀取,后期再修改數(shù)據(jù)源類。因?yàn)槭褂脭?shù)據(jù)源類需要保持與標(biāo)準(zhǔn)IO的寫(xiě)法一致( cin>>xx ),所以這個(gè)類要為每種基本類型重載輸入流操作符。這些重載的代碼結(jié)構(gòu)都是一樣的,只是數(shù)據(jù)類型不同,因此用模板是最好的,所以一開(kāi)始,我寫(xiě)成了下面這個(gè)樣子:
程序2
class DataFromFile

{
public:
DataFromFile(CHAR const *a_fileName)
:dataStream(a_fileName, std::ios::binary|std::ios::in)
{ assert(dataStream.good());}
~DataFromFile() 
{ dataStream.close();}
public:
template <typename T>
inline DataFromFile& operator>> (T& a_data) 
{
dataStream.read((CHAR *)&a_data, sizeof(T));
return *this;
}
private:
std::fstream dataStream;
};
但在實(shí)際使用時(shí),像下面的語(yǔ)句,就發(fā)生了編譯問(wèn)題:
DataFromFile source("11.bin");
A dest;
source>>dest;
編譯器對(duì)這段代碼抱怨,說(shuō)無(wú)法確定使用哪個(gè)模板……
當(dāng)然,我是希望編譯器在這里使用程序一中的非成員模板函數(shù),然后在那個(gè)模板函數(shù)中,再用程序2中的成員模板函數(shù)來(lái)實(shí)例化基本類型的輸入操作。可是編譯器沒(méi)有這么智能,我理解,這里用A做模板參數(shù)的話,確實(shí)有二義性。
想來(lái)想去沒(méi)想到好的辦法消除這種二義性,只好修改代碼,去掉其中一個(gè)的模板定義。類比地思考一下,標(biāo)準(zhǔn)IO并沒(méi)有發(fā)生這個(gè)問(wèn)題,因?yàn)闃?biāo)準(zhǔn)IO的輸入流操作并不是模板函數(shù),而這里的DataFromFile類,明顯使用模板會(huì)比較優(yōu)雅,但二義性的問(wèn)題不知道怎么解決。最后沒(méi)辦法,改成用宏來(lái)實(shí)現(xiàn),代碼如下:
程序3
#define InputForBuildIn(Type) \
inline DataFromFile& operator>> (Type& a_data) \

{ \
dataStream.read((CHAR *)&a_data, sizeof(Type)); \
return *this; \
}
class DataFromFile

{
public:
DataFromFile(CHAR const *a_fileName)
:dataStream(a_fileName, std::ios::binary|std::ios::in)
{ assert(dataStream.good());}
~DataFromFile() 
{ dataStream.close();}
public:
InputForBuildIn(INT8)
InputForBuildIn(UINT8)
InputForBuildIn(INT16)
InputForBuildIn(UINT16)
InputForBuildIn(INT32)
InputForBuildIn(UINT32)
private:
std::fstream dataStream;
};
問(wèn)題是沒(méi)有了,但總覺(jué)得不是滋味。(不知道有沒(méi)有更好的解決辦法?哪位大俠指點(diǎn)下?)
PS:
對(duì) C++ 的標(biāo)準(zhǔn) IO 流還不熟,在以二進(jìn)制方式打開(kāi)文件時(shí),使用 >> 操作符無(wú)法讀入數(shù)據(jù)?一開(kāi)始的時(shí)候調(diào)了很久,后來(lái)才發(fā)現(xiàn)這里可能有問(wèn)題,轉(zhuǎn)成使用 .read() 方法來(lái)讀數(shù)據(jù),就成功了。標(biāo)準(zhǔn) IO 還是得好好再補(bǔ)補(bǔ)啊。









}
}