使用虚拟继承的功能非虚拟?

时间:2009-11-26 15:41:02

标签: c++ inheritance virtual abstract

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

类Hierarchy看起来像这样

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

这意味着序列化不同类的对象有很多种可能的情况。例如,容器应该调用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;
}

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

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

感谢任何帮助。

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

好吧,上次我在写这个问题的时候很匆忙。代码现在更像我尝试编译时的代码。我解决了问题,我遇到的问题与提出的问题无关。我很惭愧地说它是由于代码的大量重构之后的错误引起的,以及运算符没有在每个基类中实现的事实。

非常感谢你的回复!

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:3)

这不是重载运算符&lt;&lt; ostream的作品。左手操作符是一个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;
    }
};