2

有一个类 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 对象的指针,以便 operator << 正确替换 print() 方法?这种重载是错误的

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

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

 o << (A)(bb);

3]有没有更好的方法如何在没有“朋友”声明的情况下重载运算符<<?

谢谢你的帮助....

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::print在你传递给它一个B实例时调用。

于 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();

...

我经常使用这个概念,因为它允许您指定一个打印并将其用于不同的流。我必须至少使用我提到的三个,所以对我来说它值得复杂。朋友们不在你的班级里,所以打字少了,从继承中很明显你的班级是可打印的。轻微的缺点是您在每个使用 OutEnabled 的类中都有一个模板。

于 2012-07-21T19:07:14.293 回答