我正在为我的游戏实现一个ResourceManager,我遇到了一个关于流的小问题。
在“资源管理器”中,有一个Locator对象搜索文件。当定位器找到文件时,它返回一个ResourceStream对象(virtual ResourceStream * FileLocator::locateFile(const String &name);)。然后,Loader对象解析文件并创建一个资源对象(例如virtual Resource * ResourceLoader::parseStream(ResourceStream * stream);)。
问题是,我不知道如何实现ResourceStream,因为我不知道std::streams是如何使用的。作为一种良好的实践,流是如何在对象之间传递的?是通过指针传递还是移动语义,考虑到流将在作用域的末尾被删除?在上面的问题中,我应该如何使溪流移动?我应该让ResourceStream继承自std::fstream并由std::move传递吗?还是应该使用ResourceStream作为std::streambuf的包装器?
发布于 2014-01-06 16:22:18
考虑实现一个流缓冲器 (可以作为参数传递)。当需要缓冲区上的I/O时,在缓冲区上创建一个std::istream或std::ostream。
这种方法将允许您使用std::[i/o]stream访问正确格式化的I/O,而无需付出任何努力(也就是说,您只需定义从流中添加或获取字节意味着什么,而不是格式化。
代码应该如下所示:
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"};
}编辑:
再看一看,这似乎是x-y问题。正确的解决方案是为资源类定义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发布于 2014-01-06 16:20:59
通常的解决方案是通过引用传递,但是根据您的描述,流将在一个单独的函数中创建并返回,并且应该存在于创建函数的生存期之后。传统上,您会返回一个指向动态分配的流的指针,被调用者必须删除该流。(这就是std::auto_ptr设计的目的。)在C++11中,这个解决方案仍然有效(但您可能希望使用std::unique_ptr )。或者,您可以为返回使用移动语义,尽管它们不尊重多态类型。换句话说:如果locateFile创建了一个std::ifstream,那么您用它的返回值初始化的局部变量必须是一个std::ifstream,而不仅仅是一个std::istream。这可能暴露了太多的locateFile内部,并使std::auto_ptr/std::unique_ptr解决方案更可取。
发布于 2014-01-06 16:22:26
有三种通过溪流的方法(我认为):
https://stackoverflow.com/questions/20954061
复制相似问题