仮想的に継承された関数を非仮想的に使用していますか?
-
05-07-2019 - |
質問
ゲーム内のいくつかのクラスをシリアル化する機能を実装しようとして問題が発生しました。生のテキストファイルにいくつかのデータを保存します。保存したり、そこからロードしたりできます。 ただし、これの詳細は無関係です。問題は、保存ファイルにとって興味深い各オブジェクトを自分自身でシリアライズできるようにしようとしていることです。このために、私はoperator <!> lt; <!> lt;の純粋に仮想的な宣言でISerializableインターフェイスを定義しました。およびoperator <!> gt; <!> gt;。
クラス階層は次のようになります
-> GameObject -> Character -> Player ...
ISerializable -> Item -> Container ...
-> Room ...
これは、異なるクラスのオブジェクトをシリアル化するための多くの可能な状況があることを意味します。たとえば、コンテナはoperator <!> lt; <!> lt;を呼び出す必要があります。含まれるすべてのアイテム。
今、演算子<!> gt; <!> gt; 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
機能のようなものを探していると思います。
ご協力いただければ幸いです。
-編集に関するコメント ------------
さて、前回質問を書いていたときに急いでいました。コードは、コンパイルしようとしたときのようになりました。質問を修正しましたが、私が抱えていた問題は質問とは無関係でした。コードの大規模なリファクタリングの結果としてのエラーと、すべての基本クラスに演算子が実装されていなかったという事実が原因であると言って恥ずかしく思います。
ただし、返信に感謝します!
解決
問題は、仮想関数を仮想的に呼び出そうとしないことです。問題は次の行です: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;
}
他のヒント
これは、演算子<!> 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;
}
};