3

具体来说,我希望能够ostream operator <<在一个基类的两个派生类中使用。

我正在创建的程序应该打印出“虚拟商店”中各种“产品”的产品详细信息。产品中有两种不同的书籍。这些书中的每一本书都应该拥有自己的:

ID number
Author
NumberOfPages
Year

此外,typeChildrensBook需要持有最低年龄,并且TextBook需要持有一个等级。

我定义了类Book并从它派生了类ChildrensBookTextBook. 我的问题是关于使用ostream operator <<打印信息。

能否在Book类中定义一个通用的<<函数,打印出两个派生类共有的所有信息,然后在派生类中重新定义<<时引用它?

例如,

//The parent class

ostream& operator<<(ostream& bookOutput, const Book& printBook) {
    return bookOutput << printBook.ID << "Name " << printBook.name << "year:" << printBook.year";
}

然后在派生类中以某种方式:

//The derived classes
ostream& operator<<(ostream& TextBookOutput, const TextBook& printTextBook) {
    return TextBookOutput << "TextBook: " 
           << "[Here is where I want to print out all the details of the book that are members of the base class]" << "Grade:" << printTextBook.grade;
}

所以我想我的问题可以总结为:我可以从子运算符中调用父运算符吗?如果可以,我使用什么语法?

我想到的另一个想法是为使用父打印运算符的孩子编写一个函数,然后从孩子的打印运算符中调用该函数。这意味着我在重新定义运算符时并没有尝试调用它,但仍然要求使用父运算符并单独重新定义子运算符。

4

3 回答 3

4

当然。

你有一个Books 的运算符,所以使用它。您可以通过为其提供对一本书的引用来调用它,并且您可以使用多态性的力量来获得对基的引用。

ostream& operator<<(ostream& TextBookOutput, const TextBook& printTextBook) {
    return TextBookOutput << "TextBook: " << static_cast<const Book&>(printTextBook) << "Grade:" << printTextBook.grade;
}
于 2011-05-09T10:46:59.713 回答
0
return TextBookOutput << static_cast<Book const &>(printTextBook) << ...
于 2011-05-09T10:41:40.163 回答
0

正如其他人指出的那样,您应该使用向下转换来实现您的要求。但我认为您也应该考虑一种不同的方法:您现在正在做的是混合静态动态多态性,这通常不是一个好主意(通常只会在以后表现出来)。

这是问题所在,请考虑您已经拥有的内容:

class Book { ... };
class TextBook : public Book { ... };
ostream& operator<<(ostream& os, const Book& book) {
    return os << "Book: " << book.name << "\n";
}
ostream& operator<<(ostream& os, const TextBook& book) {
    return os << "TextBook: " << book.name << "\n";
}
如果您像这样使用它,一切都会按预期进行:
Book book;
TextBook textBook;
cout << book << "\n";     // prints out: Book: XYZ
cout << textBook << "\n"; // prints out: TextBook: XYZ 
那是因为编译器将在编译期间(静态)正确地确定书的类型。

现在考虑另一种情况:

Book * textBook = new TextBook();
cout << *textBook << "\n";    // prints out: Book: XYZ !

这是因为编译器无法知道它是什么更高的类型,它可以是 Book、TextBook 或 ChildrensBook。这只能在运行时(动态)使用虚拟函数等来确定。

因此,如果您考虑使用动态多态性,我更喜欢这种方法:

class Book {
  public:
  virtual ostream& print(ostream& os) const { return os << "Book: XYZ"; }
  // Don't forget virtual destructor.
  virtual ~Book() {}
};
class TextBook : public Book {
  public:
  virtual ostream& print(ostream& os) const
  {
    // Here, you can also call the "print" method of the parent class
    // like this: os << Book::print(os);
    // or just invent your own like this:
    return os << "TextBook: XYZ";
  }
};
ostream& operator<<(ostream& os, const Book& book) {
  // Will correctly decide during runtime whether
  // to use Book::print or TextBook::print.
  return book.print(os);
}

于 2011-05-09T12:02:59.097 回答