2

仮想メソッドprint()とオーバーロードされた演算子<<をフレンド関数として定義したクラスAがあります。

#include <iostream>
class A
{
public:
    double a1, a2;
    A(): a1(10.0), a2(10.0) {}

    virtual void print ( std::ostream * o = &std::cout ) const
    {
        *o << a1<< '\t' << a2 << '\n';
        }

    friend std::ostream & operator << ( std::ostream & o, const A &aa )
    {
        o << aa.a1 << '\t' << aa.a2 << '\n';
        return o;
    }
};

同様に、派生クラスBでも

 class B : public A
 {
public:
    double b1, b2;
    B(): A(), b1(20.0), b2(20.0) {}

    virtual void print ( std::ostream * o = &std::cout ) const
    {
        A::print ( o );
        *o << b1<< '\t' << b2;
    }

    friend std::ostream & operator << ( std::ostream & o, const B &bb )
    {
        o << (A)(bb);
        o << bb.b1 << '\t' << bb.b2 << '\n';
        return o;
    }
 };

次の質問があります。

1]演算子<<がprint()メソッドを正しく置き換えるように、デフォルトのパラメータを使用してostreamオブジェクトへのポインタを渡す方法はありますか?このオーバーロードは間違っています

friend std::ostream & operator << ( std::ostream * o= &std::cout, const A &aa )

2]派生クラスBの親クラスAのこの行呼び出し演算子が正しいかどうかはわかりませんか?

 o << (A)(bb);

3]「friend」宣言なしで演算子<<をオーバーロードするより良い方法はありますか?

ご協力いただきありがとうございます....

4

2 に答える 2

1

あなたは友情なしでこのようにそれをすることができます:

#include <iostream>
class A
{
    double a1, a2;

public:
    A(): a1(10.0), a2(10.0) {}

    virtual void print ( std::ostream * o = &std::cout ) const
    {
        *o << a1 << '\t' << a2;
    }
};

std::ostream & operator << ( std::ostream & o, const A &aa )
{
    o << "( )";
    aa.print(&o);
    return o << " )";
}

の別のバージョンではありclass Bません。これが検出され、インスタンスを渡すときにoperator<<呼び出されます。B::printB

于 2012-07-21T19:05:00.427 に答える
1

私は長い間、冗長な友達宣言を回避する方法について疑問に思い、次のことを考え出しました。

template<typename T>
class OutEnabled {
  public:
    friend std::ostream& operator<<(std::ostream& out, T const& val) {
      return static_cast<OutEnabled<T> const&>(val).ioprint(out);
    }

    friend QTextStream& operator<<(QTextStream& out, T const& val) {
      return static_cast<OutEnabled<T> const&>(val).ioprint(out);
    }

    friend QDebug operator<<(QDebug dbg,T const& val) {
      std::stringstream myStream;
      myStream << val;
      dbg.maybeSpace() << myStream.str().c_str();
      return dbg;
    }

  protected:
    template<typename U>
    U& ioprint(U& out) const {
      return static_cast<T const*>(this)->print(out);
    }
};

class Foo:public OutEnabled<Foo>{
  public:
    Foo(){}

    template<typename V>
    V& print(V& out) const{return out<< "Bar";}
};

これを書く私は書くことができます:

std::cout << Foo();
qDebug() << Foo();

..。

このコンセプトは、1つのプリントを指定して、さまざまなストリームに使用できるため、よく使用します。私は少なくとも私が言及した3つを使用する必要があるので、私にとっては複雑にする価値があります。友達はあなたのクラスの外にいるのでタイピングが少なく、あなたのクラスが印刷可能であることは継承から明らかです。わずかな欠点は、OutEnabledを使用するすべてのクラスにテンプレートがあることです。

于 2012-07-21T19:07:14.293 に答える