2

这是在ostream& operator<<不复制基类代码的情况下为派生类重载的唯一方法吗?演员表不是应该避免的吗?

我没有看到任何其他方式,除了在基类中定义某种函数,它将基类的数据表示为 std::operator<< 可以“吃掉”(如字符串?)的东西,对派生类做同样的事情(在派生类流中调用基类流表示函数。当然是代表函数)。

这个问题的理想解决方案是什么?

#include <iostream>

class Base
{
    private: 
        int b_;
    public: 
        Base()
            :
                b_()
        {};

        Base (int b)
            : 
                b_(b)
        {};

        friend std::ostream& operator<<(std::ostream& os, const Base& b);
};

std::ostream& operator<< (std::ostream& os, const Base& b)
{
    os << b.b_; 
    return os;
}

class Derived
:
    public Base
{
    private: 
        int d_;
    public: 
        Derived()
            :
                d_()
        {};

        Derived (int b, int d)
            : 
                Base(b), 
                d_(d)
        {};

        friend std::ostream& operator<<(std::ostream& os, const Derived& b);
};

std::ostream& operator<< (std::ostream& os, const Derived& b)
{
    os << static_cast<const Base&>(b) << " " << b.d_; 
    return os;
}



using namespace std;


int main(int argc, const char *argv[])
{
    Base b(4);

    cout << b << endl;

    Derived d(4,5);

    cout << d << endl;

    return 0;
}
4

4 回答 4

6

好吧...如果在结果未正确定义的情况下进行转换,则应避免转换,但转换为基础始终是安全的。

可以通过考虑派生引用衰减到基引用来避免显式转换,因此您可以使用隐式转换,例如在这种情况下:

std::ostream& operator<< (std::ostream& os, const Derived& b)
{
    const Base& bs = b;
    os << bs << " " << b.d_; 
    return os;
}
于 2012-05-23T19:01:49.683 回答
5
static_cast<const Base&>(b)

是安全的,没有什么不正确的,因为每个派生类对象也是一个基类对象,可以像一个对象一样对待。

强制转换只有在鲁莽使用时才是危险的,您必须在需要的地方以正确的方式使用强制转换,这正是语言标准提供它们的目的。

于 2012-05-23T18:33:18.070 回答
1

你可以改变这样的事情:

struct Base {
    int b_;
    void print(ostream &o) { o << b_; }
};

struct Derived : Base {
    int d_;
    void print(ostream &o) {
        Base::print(o);
        o << ' ' << d_;
   }
};

ostream &operator<<(ostream &o, Base &b) {
    b.print(o);
    return o;
}

ostream &operator<<(ostream &o, Derived &d) {
    d.print(o);
    return o;
}

如果Base有虚函数(在这个例子中没有),那么print可能是其中之一,你可以摆脱operator<<.

于 2012-05-23T19:09:21.403 回答
1

如果您不喜欢强制转换,您可以让您的操作员调用writeTo使用模板方法模式实现的函数。

例如

class Base {
   public:
       std::ostream& writeTo(std::ostream& ostr) const { os << b_; return this->doWriteTo(os); }
   private:
       int b_;

       virtual std::ostream& doWriteTo(std::ostream& ostr) const = 0; // pure virtual
};


class Derived {
    private:
        int d_;
        virtual std::ostream& doWriteTo(std::ostream& ostr) const {return ostr << d_;}
};

std::ostream& operator<<(std::ostream& ostr, const Derived& d) {
  return d.writeTo(ostr);

}

实际上,使用这种模式,您可以operator<<一劳永逸地编写Base

std::ostream& operator<<(std::ostream& ostr, const Base& b) {
  return b.writeTo(ostr);

}

这种模式也消除了operator<<制作friend.

于 2012-05-23T19:14:06.687 回答