2

ゲーム内の一部のクラスをシリアル化する機能を実装しようとして問題が発生しました。一部のデータを未加工のテキスト ファイルに保存しており、保存したり読み込んだりできるようにしたいと考えています。ただし、これの詳細は関係ありません。問題は、保存ファイルにとって興味深い各オブジェクトをシリアル化できるようにしようとしていることです。このために、operator<< と operator>> の純粋な仮想宣言を使用して、インターフェイス ISerializable を定義しました。

クラス階層はこんな感じ

              -> 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::ostreamoperator=.

とにかく、割り当ては必要ありません。The stream returned is the same stream as the stream you pass in. それが返される唯一の理由は、それらを連鎖できるようにするためです。

したがって、修正はコードを次のように変更することです

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 に答える