2

我在尝试实现在我的游戏中序列化某些类的功能时遇到了麻烦。我将一些数据存储在一个原始文本文件中,我希望能够保存和加载到它/从它加载。然而,这方面的细节是无关紧要的。问题是我正在尝试使每个对保存文件感兴趣的对象都能够自行序列化。为此,我定义了一个接口 ISerializable,其中包含 operator<< 和 operator>> 的纯虚拟声明。

类层次结构看起来像这样

              -> GameObject -> Character -> Player ...
ISerializable               -> Item -> Container ...
              -> Room ...

这意味着序列化不同类的对象有很多可能的情况。例如,容器应该在所有包含的项目上调用 operator<<。

现在,由于 operator>> 是虚拟的,我想如果我想序列化实现 ISerializable 中定义的功能的东西,我可以做类似的事情

ostream & Player::operator<<(ostream & os){
    Character::operator<<(os);
    os << player_specific_property 1 << " " 
       << player_specific_property 2 << "...";
    return os;
}

进而

ostream & Character::operator<<(ostream & os){
    GameObject::operator<<(os);
    os << character_specific_property 1 << " " 
       << character_specific_property 2 << "...";
    return os;
}

但我很快就知道这第一次尝试是非法的。我在这里问的是如何解决这个问题

我不想为每个类手动实现一个函数。我想我正在寻找类似superJava 的功能。

任何帮助表示赞赏。

--编辑评论------------

好吧,上次我写问题的时候很着急。现在的代码更像是我尝试编译它时的样子。我解决了这个问题,我遇到的问题与提出的问题无关。我很惭愧地说这是由于对代码进行大规模重构后出现的一个错误,以及该运算符并未在每个基类中都实现的事实。

非常感谢您的回复!

4

2 回答 2

4

问题不在于您尝试以非虚拟方式调用虚函数。问题是这一行:os = Character::operator<<(os);. 这是一个任务,但std::ostream没有operator=.

反正你不需要这个任务。返回的流与您传入的流是相同的流。它返回的唯一原因是您可以将它们链接起来。

因此,解决方法是将代码更改为

ostream & Player::operator<<(ostream & os){
    Character::operator<<(os);
    os << player_specific_property 1 << " " 
       << player_specific_property 2 << "...";
    return os;
}
于 2009-11-26T15:54:39.070 回答
3

这不是 ostream 的重载 operator<< 的工作方式。左边的运算符是一个 ostream (因此你必须将它作为一个自由函数重载),右边的运算符是你的对象(这就是为什么虚拟机制不容易工作的原因。

我想你可以试试:

class Base
{
    //...
    virtual std::ostream& output(std::ostream&) const;
};

std::ostream& operator<< (std::ostream& os, const Base& obj)
{
    return obj.output(os);
}

现在派生类自然可能会调用其父类的输出方法:

class Derived: public Base
    //...
    virtual std::ostream& output(std::ostream& os) const
    {
        Base::output(os);
        return os << my_specific_data;
    }
};
于 2009-11-26T16:22:30.547 回答