C ++:运算符<<在带有默认参数的派生类中?

时间:2012-07-21 18:32:42

标签: c++ stream operator-overloading

有一个类A具有虚方法print()和重载运算符<<定义为朋友功能。

#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]有没有办法如何使用默认参数传递指向ostream对象的指针,以便运算符&lt;&lt;正确地替换了print()方法?这种重载是错误的

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

2]我不确定,如果派生类B中父类A的这一行调用操作符是正确的吗?

 o << (A)(bb);

3]有没有更好的方法来重载operator&lt;&lt;没有&#34;朋友&#34;声明?

感谢您的帮助......

2 个答案:

答案 0 :(得分: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::print个实例传递时调用B。< / p>

答案 1 :(得分: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();

...

我经常使用这个概念,因为它允许您指定一个打印并将其用于不同的流。我必须至少使用我提到的三个,所以对我而言,这是值得的复杂性。这些朋友不在你的课堂上,所以打字很少,从继承中可以看出你的班级是可打印的。稍有不利的是,每个使用OutEnabled的类都有一个模板。