C++ 从文件设计加载对象

C++ 从文件设计加载对象,c++,C++,从文件加载对象的最佳设计是什么?有很多可能性,其中一些如下所示 class object { public: object(const std::string& filename); }; class object { public: object(); void load_from_file(const std::string& filename); }; class object { public: static object load_f

从文件加载对象的最佳设计是什么?有很多可能性,其中一些如下所示

class object
{
public:
    object(const std::string& filename);
};

class object
{
public:
    object();
    void load_from_file(const std::string& filename);
};

class object
{
public:
    static object load_from_file(const std::string& filename);

    object(object&& an_object);
};

class object
{
public:
    std::unique_ptr<object> load_from_file(const std::string& filename);
};

class object_loader
{
public:
    std::unique_ptr<object> load_object_from_file(const std::string& filename);
};

我更喜欢“class object_loader”,它将IO加载器与容器分离,允许将来实现不同的加载器(来自txt、二进制、xml…文件),而无需修改原始数据容器。更好的测试是可能的。如果不允许IO(如嵌入式设备等),也可以从应用程序中删除IO

我更喜欢“class object_loader”,它将IO加载器与容器分开,允许将来在不修改原始数据容器的情况下实现不同的加载器(来自txt、二进制、xml…文件)。更好的测试是可能的。如果不允许IO(如嵌入式设备等),也可以从应用程序中删除IO

从文件加载对象的最佳设计是什么

最佳设计通常遵循以下原则:

class object { public: object(); /* ... */ }; // object is default constructible

std::istream& operator >> (std::istream& in, object& o);
客户端代码:

// from file:
std::ifstream fin(path);
object o;
fin >> o;
// from serialized string:
std::string contents = ".....";
std::istrigstream ssin(contents);
ssin >> o;
编辑:

事务实现:

std::istream& operator >> (std::istream& in, object& o)
{
    int i; std::string word; // example data required by object instance
    if (in >> i >> word)
    { // read was successful for all data
        o.set_index(i);
        o.set_word(word);
    }
    return in;
}

// client code:
if(ssin >> o)
{ // read was successful
    // use o here
} else {
    // o is still as default-constructed
}
如果流在错误时抛出异常,这种方法也会起同样的作用

从文件加载对象的最佳设计是什么

最佳设计通常遵循以下原则:

class object { public: object(); /* ... */ }; // object is default constructible

std::istream& operator >> (std::istream& in, object& o);
客户端代码:

// from file:
std::ifstream fin(path);
object o;
fin >> o;
// from serialized string:
std::string contents = ".....";
std::istrigstream ssin(contents);
ssin >> o;
编辑:

事务实现:

std::istream& operator >> (std::istream& in, object& o)
{
    int i; std::string word; // example data required by object instance
    if (in >> i >> word)
    { // read was successful for all data
        o.set_index(i);
        o.set_word(word);
    }
    return in;
}

// client code:
if(ssin >> o)
{ // read was successful
    // use o here
} else {
    // o is still as default-constructed
}


如果流在错误时抛出异常,这种方法也会起同样的作用。

坦率地说,您根本不应该传递文件名。您应该传递一个
istream
引用。类不需要知道字节来自何处;它只需要一种读取字节并理解它们的方法。好主意。不过,哪种设计是最好的(想象一下const std::string&filename被std::istream&input_stream取代)?@cHao:我对这个问题的看法随着时间的推移而剧烈波动。原则上我并不反对你的观点,但有时从调用站点中抽象出所有那些文件废话是很好的,在某些应用程序中这是有意义的。@LightnessRacesinOrbit:我想如果你确定这些对象只来自一个文件,而一个文件正好包含一个,简单地传递一个文件名可能是有意义的。但在我看来,你可以很容易地创建一个模板函数,专门从文件中加载一个对象——这将抽象掉文件内容,而不会牺牲从其他来源取消序列化对象的能力。坦率地说,你根本不应该传递一个文件名。您应该传递一个
istream
引用。类不需要知道字节来自何处;它只需要一种读取字节并理解它们的方法。好主意。不过,哪种设计是最好的(想象一下const std::string&filename被std::istream&input_stream取代)?@cHao:我对这个问题的看法随着时间的推移而剧烈波动。原则上我并不反对你的观点,但有时从调用站点中抽象出所有那些文件废话是很好的,在某些应用程序中这是有意义的。@LightnessRacesinOrbit:我想如果你确定这些对象只来自一个文件,而一个文件正好包含一个,简单地传递一个文件名可能是有意义的。但在我看来,你可以很容易地创建一个模板函数,专门从文件中加载一个对象,这样可以在不牺牲从其他来源取消序列化对象的能力的情况下抽象出文件内容。很好,我没有想到这一点。但是,如果默认构造对象没有意义呢?object(std::istream&input_stream)会是更好的选择吗?模式很好,但是您将无法从不同的文件类型加载对象(如果将来需要支持从txt、xml等加载)@Cole,如果您可以保证流中的对象被正确序列化,那么这会更有意义(否则,
o
将处于无效状态)。@dousin非常正确。我现在倾向于使用接受istream引用的对象\u加载程序。不过,我还有两个问题。1)你认为我应该从加载函数或对象(调用移动构造函数)返回unique\u ptr吗?2) 加载函数是否应该是静态的?@utnapistim True。我想无论是否使用默认构造函数,都无法避免无效的对象状态。很好,我没有想到这一点。但是,如果默认构造对象没有意义呢?object(std::istream&input_stream)会是更好的选择吗?模式很好,但是您将无法从不同的文件类型加载对象(如果将来需要支持从txt、xml等加载)@Cole,如果您可以保证流中的对象被正确序列化,那么这会更有意义(否则,
o
将处于无效状态)。@dousin非常正确。我现在倾向于使用接受istream引用的对象\u加载程序。不过,我还有两个问题。1)你认为我应该从加载函数或对象(调用移动构造函数)返回unique\u ptr吗?2) 加载函数是否应该是静态的?@utnapistim True。我想无论是否使用默认构造函数,都无法避免无效的对象状态。我会投票决定答案,但我还没有足够的声誉,所以谢谢!别担心,我可以投票表决:我会投票表决的答案,但我还没有足够的声誉,所以谢谢!别担心,我可以投票表决:D