1

C ++ FAQで説明されているように、クラス階層の印刷パターンを実装しています。FAQでは、印刷関数は次のように基本クラスで宣言されています。

protected:
  virtual void printOn(std::ostream& o) const = 0;  // pure virtual
  // -- or --
  virtual void printOn(std::ostream& o) const;      // plain virtual

メソッドのプレーン仮想バージョンを実装することを検討していますprintOnが、バリエーションがあります。voidここに示すように、リターンタイプをからに変更したいと思いstd::ostream&ます。

protected:
  virtual std::ostream& printOn(std::ostream& o) const;

私が見ているこのアプローチの利点は、連鎖アプローチを使用して、基本クラスの出力を派生クラスの出力に簡単に組み込むことができることです。次に例を示します。

std::ostream& DerivedClass::printOn(std::ostream& stream) const
{
  return stream
      << "<DerivedClass>" << '\n'
      << BaseClass::printOn(stream)
      << "<member_one>" << member_one_ << "</member_one>" << '\n'
      << "<member_two>" << member_two_ << "</member_two>" << '\n'
      << "</DerivedClass>" << std::endl;
}

対照的に、FAQに示されているようにDerivedClass::printOn仮想BaseClass::printOnメソッドが宣言されている場合は次のようになります。void

void DerivedClass::printOn(std::ostream& stream) const
{
    stream << "<DerivedClass>" << '\n';
    BaseClass::printOn(stream);

    stream
        << "<member_one>" << member_one_ << "</member_one>" << '\n'
        << "<member_two>" << member_two_ << "</member_two>" << '\n'
        << "</DerivedClass>" << std::endl;
}

 

質問:返品タイプの改訂案で落とし穴を見つけた人はいますprintOnか?

4

1 に答える 1

2

BaseClass::printOn(stream)a を返す場合は、std::ostream &書き込みできません

stream << ... << BaseClass::printOn(stream) << ...;

あなたは書く必要があります:

stream << ...;
BaseClass::printOn(stream) << ...;

明らかに、これは を返す場合よりもほとんど良くありませんvoid。no-op ストリームアウト演算子を使用して型を返すことができます。

struct noop_manipulator {
  noop_manipulator(std::ostream &) {}
  friend inline std::ostream &operator<<(std::ostream &os, const noop_manipulator &) {
    return os;
  }
};

noop_manipulator DerivedClass::printOn(std::ostream& stream) const
{
    return stream << ...;
}

または、構文をいじることもできます。

void DerivedClass::printOn(std::ostream& stream) const
{
    return stream << "<DerivedClass>" << '\n',
        BaseClass::printOn(stream), stream
        << "<member_one>" << member_one_ << "</member_one>" << '\n'
        << "<member_two>" << member_two_ << "</member_two>" << '\n'
        << "</DerivedClass>" << std::endl;
}

これらすべてのアプローチの欠点は、スーパークラスの仮想呼び出しの使用がわかりにくくなることです。これは非常に珍しいため、できる限り明確にする必要があります。説明されている印刷パターン自体はかなり珍しいものです。すでに仮想継承階層を持っていない限り、派生クラスが独自のものを持ち、基本クラス参照を介して基本operator<<クラスを呼び出すのがより一般的です。operator<<static_cast

于 2013-02-14T21:45:12.393 に答える