重载<<和>>在继承的类中

时间:2010-11-12 13:08:03

标签: c++ inheritance operators overloading

我有类Person(名字,姓氏,地址,年龄)和重载运算符<<和>>与文件流一起使用:

ostream& operator<< (ostream& outStream, Person& person)
{
  ...
}

istream& operator>> (istream& inStream, Person& person)
{
  ...
}

它工作正常 - 我可以轻松地读取和写入文件,但我添加了两个继承自Person:Student和Worker的类。

我为他们编写了重载操作符,与上面的操作符非常相似:

ostream& operator<< (ostream& outStream, Worker& worker)
{
 ...
}

istream& operator>> (istream& inStream, Worker& worker)
{
 ...
}


ostream& operator<< (ostream& outStream, Student& student)
{
 ...
}

istream& operator>> (istream& inStream, Student& student)
{
 ...
}

唯一不同的是每个班级还有两个字段。问题是,当我使用Student或Worker重载运算符时,我的编译器似乎使用运算符。可能它会从Student或Worker到Person进行隐藏转换,但结果是没有写入该文件的其他字段。 offstream&lt;&lt;人们的工作方式与offstream&lt;&lt;学生或工人。 也许首先为继承的类放置重载的运算符声明,然后在代码中为Person解决问题,但我不认为它是一个优雅的解决方案。

如果您对如何解决上述问题有一些想法,我将不胜感激。

4 个答案:

答案 0 :(得分:12)

两件事。首先,让你的运算符接受const的引用,如下所示:

ostream& operator<< (ostream& outStream, const Person& person)

要解决您的问题,常见的模式是为您的类型提供受保护的虚拟toString方法,并让操作员调用它。然后,您可以在子类中重载此方法,如果您只想在字符串中附加一些值,甚至可以重用超类实现。

示例:

class Person {
// other stuff
protected:
    virtual std::string toString();
    friend ostream& operator<< (ostream& outStream, const Person& person)
};

ostream& operator<< (ostream& outStream, Person& person)
{
    ostream << person.toString();
    return outStream;
}

修改 实际上,我更喜欢larsmans的建议:

class Person {
// other stuff
protected:
    virtual void print(ostream & stream) const;
    friend ostream& operator<< (ostream& outStream, const Person& person)
};

ostream& operator<< (ostream& outStream, Person& person)
{
    person.print(outStream);
    return outStream;
}

这比toString想法更容易实现,因为您不需要临时stringstream或类似的东西来构建字符串。

答案 1 :(得分:3)

调用<<运算符的代码很可能通过指向 Person 的指针或引用来访问对象,从而调用 Person 类型的运算符。处理此问题的常用方法是在父类(即 Person )类上提供虚拟方法,该类执行写入(将流作为参数),并让operator<<调用此方法做工作的方法。您只需要为父类提供operator<<,虚拟调度机制将负责为所提供的对象选择正确的方法。

class Person {
   // ...
protected:
   virtual ostream& stream_write(ostream&) const;  //override this in child classes
   virtual istream& stream_read(istream&);        //this too
public:
   friend ostream& operator<< (ostream& stream, const Person& obj)
      { return obj.stream_write(stream); }
   friend istream& operator>> (istream& stream, Person& obj)
      { return obj.stream_read(stream); }
};

答案 2 :(得分:2)

您的操作员可以调用虚拟方法。像这样:

struct A
{
  virtual ~A(){}

  virtual std::ostream& Print( std::ostream &os ) const
  {
    // print what you want
    return os;
  }
};

struct B : A
{
  virtual ~B(){}

  virtual std::ostream& Print( std::ostream &os ) const
  {
    // print what you want
    return os;
  }
};

然后创建运算符&lt;&lt;仅适用于基类:

std::ostream& operator<<( std::ostream &os, const A &a)
{
  return a.Print(os);
}

答案 3 :(得分:0)

我通常在重载的流操作符中调用虚函数streamIn和streamOut,这样我实际上可以创建一个模板流函数,该函数适用于所有具有streamIn和streamOut函数的类。