[英]C++ How to dynamically select a file handle according to the type of data that should be written?
我有一個class outputInterface;
應該處理一些數據的輸出(到文件)。 數據包含在某些自定義類的對象中,例如dataClassA
和dataClassB
,它們都從通用基類dataClassBase
派生。
現在,我希望根據數據類型將數據寫入不同的文件。 因此, dataClassA
類型的數據應轉到fileA
, dataClassB
類型的數據應轉到fileB
,依此類推。 由於此輸出經常發生,因此我希望文件句柄( fileA
和fileB
)保持打開狀態,即,我不想打開和關閉用於輸出每個數據的文件。 可以一直認為存在一個outputInterface
對象。
所以我想要實現的是這樣的:
dataClassA
類型的數據與文件句柄fileA
等動態關聯。 dataClassA
類型的數據時,請檢查fileA
是否已連接到文件,如果沒有,請打開該文件。 如何獲得這種行為(或至少類似/更好的行為)? 我一直在考慮使文件處理dataClassA
和dataClassB
(或基類dataClassBase
嗎?)的靜態成員。 但是,我該如何關閉文件呢? 我將不得不以某種方式跟蹤實際已使用的數據類型(實際已打開的文件)。
嘗試這樣的事情:
#ifndef OUTPUTINTERFACE?H
#define OUTPUTINTERFACE?H
#include <string>
#include <fstream>
#include <map>
class DataClass
{
public:
virtual bool WriteData(std::ofstream& FStream) = 0;
};
class DataClass1 :
public DataClass
{
virtual bool WriteData(std::ofstream& FStream)
{
FStream << "teletubbies";
}
};
class DataClass2 :
public DataClass
{
virtual bool WriteData(std::ofstream& FStream)
{
FStream << "garbage";
}
};
class OutputInterface
{
public:
OutputInterface()
{
}
~OutputInterface()
{
//Release stream pointers
}
template<typename T>
bool WriteData(T& Data)
{
std::string dClassUID = std::string(typeid(T).name);
tFStreamMap::iterator it this->streamMap.find(dClassUID);
std::ofstream* stream = NULL;
if(it != streamMap.end())
{
stream = it->second;
}
else
{
stream = new std::ofstream();
stream->open(dClassUID + ".txt");
streamMap.insert(std::make_pair(dClassUID, stream));
}
Data.WriteData(stream);
}
private:
typedef std::map<std::string, std::ofstream*> tFStreamMap;
tFStreamMap streamMap;
};
#endif
這只是概念的證明,可以通過多種方式進行優化。 我寧願堅持使用重載函數而不是運行時類型檢查。
這在C ++ 11中使用std::map<std::type_index, std::ostring*> outputMap
相當容易實現。 (在C ++ 03中,您必須自己實現std::type_index
的等效項。)您可以使用outputMap[typeid(*data)]
獲得輸出流。 唯一的問題是開始將流放入地圖中:您可以執行以下操作:
std::ostream*& destPtr = outputMap[typeid(*data)];
if ( destPtr == NULL ) {
destPtr = new std::ofstream("...");
}
std::ostream& dest = *destPtr;
但是,從哪里獲得文件名?
還有一個問題,當您關閉流時:您通常無法在析構函數中關閉輸出流,因為關閉輸出流是一個可能會失敗的操作,您需要檢測到該失敗並對之做出反應。 可能有一個例外,這就是為什么您不想在析構函數中這樣做。
由於“數據”部分來自dataClassBase
,因此您可以在此類中創建一個虛擬/純虛擬函數“ WriteData”,然后讓派生類實現它。
類outputInterface
可以采用dataClassBase
類型的對象,並直接調用WriteData
。 除了WriteData
您還可以在dataClassBase
添加其他虛擬函數
您沒有提到outputInterface
和dataClassBase
之間的關系
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.