2014-01-06 84 views
2

我正在爲我的遊戲實現ResourceManager,並且遇到了關於Streams的一個小問題。將std :: stream對象從一個管理器傳遞給另一個管理器

在我的資源管理器中,有一個Locator對象用於搜索文件。當定位器找到該文件時,它返回一個ResourceStream對象(virtual ResourceStream * FileLocator::locateFile(const String &name);)。然後,Loader對象解析該文件並創建一個Resource對象(例如virtual Resource * ResourceLoader::parseStream(ResourceStream * stream);)。

問題是,我不知道如何實現ResourceStream,因爲我真的不知道如何使用std :: streams。作爲一種良好的習慣,流如何在對象之間傳遞?如果考慮到它,通過指針傳遞或移動語義,流將在範圍的末尾被刪除?在上面的問題中,我應該如何讓流動?我應該讓ResourceStream從std::fstream繼承,並通過std::move?或者我應該使用ResourceStream作爲圍繞std::streambuf的包裝?

回答

1

考慮實施stream buffer(可作爲參數傳遞)。當你需要緩衝區上的I/O時,在其上創建一個std :: istream或std :: ostream。

這種方法可以讓你有機會獲得正確格式化的I/O使用std::[i/o]stream與您進行任何努力(即你只需要定義什麼增加或從流手段越來越字節,而不是格式化。

代碼應該是這樣的:

class ResourceStream: public std::streambuf { 
    ... // you implement this 
}; 

virtual Resource parseStream(std::streambuf * streambuf) 
{ 
    std::istream in(streambuf); 
    Resource  r; 
    in >> r; // assumes an std::istream& operator>>(std::istream&in, Resource& r) 
      // is defined 
    if(in >> r) 
     return r; 
    else 
     throw std::runtime_error{"bad stream for parsing resource"}; 
} 

編輯:

在第二次看,這似乎是在xy問題。正確的解決方案是定義I/O運營商爲您的資源類:

你需要寫什麼:

class Resource { 
// ... 
}; 

std::istream& operator >> (std::istream& in, Resource& r) { 
    return in after reading from it 
} 
std::ostream& operator << (std::ostream& out, const Resource& r) { 
    return in after writing into it 
} 

在模型中ResourceStream對象將是一個std :: ifstream的對文件所在的文件打開和你的ResourceManager看起來就像這樣:

// boost::path can be replaced by std::string containing the file path 
virtual boost::path FileLocator::locateFile(const String &name); 

// locate file and get resource: 
auto path = locator.locateFile("serializedresource.data"); 
std::ifstream input(path); 
Resource r; 
if(input >> r) 
    // r was read correctly 
else 
    // stream does not contain a serialized r/throw an exception 
+0

我真的很喜歡實現我自己的流緩衝區的想法,但如果我打算使用std :: [i/o] fstream,使用'basic_filebuf'會更有意義嗎?另外,當文件被加載爲二進制文本或文本或其fstream作業將其「解析」爲文本或二進制文件時,streambuf會發生變化嗎?我仍然在研究和閱讀關於streambuf,因爲我從來沒有使用過任何經驗。 – Gasim

+1

streambuf是二進制的。從字節轉換爲格式化數據是流的職責(在緩衝區之上)。 – utnapistim

1

通常的解決方案是通過引用傳遞,但是從您所描述的內容來看,流將在獨立函數中創建並返回,並且應超出創建函數的生命週期。傳統上,您會返回一個指向動態分配的流的指針,被調用者必須刪除該流。 (這是std::auto_ptr的設計目的。)在C++ 11中,此解決方案仍然有效(但您可能想使用std::unique_ptr代替)。或者,您可能可以使用移動語義進行返回,但它們不會考慮多態類型。換句話說:如果locateFile創建了一個std::ifstream,那麼用它的返回值初始化的本地變量將不得不是std::ifstream,而不僅僅是std::istream。這可能暴露了太多內部的locateFile,並且使得解決方案更可取。

1

有路過流的三種方式(我認爲):

  • 作爲參數(非常量引用的函數)
  • 作爲封裝在一個智能指針 (STD /升壓:: shared_ptr的或的unique_ptr)
  • 移動語義(編譯器可能不支持)
  • 的返回值
相關問題