派生类中的运算符重新定义但仍使用父类

发布于 2024-11-05 13:52:08 字数 1361 浏览 0 评论 0原文

具体来说,我希望能够在基类的两个派生类中使用ostream运算符<<

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

ID number
Author
NumberOfPages
Year

此外,类型 ChildrensBook 需要保留最低年龄,而 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;
}

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

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

Specifically, I would like to be able to use the ostream operator << in two derived classes from a base class.

The program I am creating is supposed to print out product details for various "products" in a "virtual store". Among the products are two different kinds of books. Each of these books is supposed to hold their own:

ID number
Author
NumberOfPages
Year

In addition, type ChildrensBook needs to hold a minimum age, and TextBook needs to hold a grade.

I defined class Book and derived from it classes ChildrensBook and TextBook. My question is about using the ostream operator << to print out the information.

Can I define a generic << function in the Book class, which will print out all of the information common to both derived classes, and then refer to it in the redefinition of << in the derived classes?

For example,

//The parent class

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

And then in the derived class somehow:

//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;
}

So I guess my question can be summed up as: Can I call the parent operator from within the child operator, and if so, what syntax do I use?

Another idea that occurred to me is to write a function for the child that uses the parent print operator, and then call that function from within the child's print operator. That would mean that I wasn't trying to call an operator while redefining it, but still calls for using the parent operator and separately redefining the child operator.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你又不是我 2024-11-12 13:52:08

当然。

您有一个用于 Book 的运算符,因此请使用它。您可以通过给它提供对一本书的引用来调用它,并且可以使用多态性的力量来获取对基的引用。

ostream& operator<<(ostream& TextBookOutput, const TextBook& printTextBook) {
    return TextBookOutput << "TextBook: " << static_cast<const Book&>(printTextBook) << "Grade:" << printTextBook.grade;
}

Sure.

You have an operator for Books, so use it. You can invoke it by giving it a reference to a book, and you can use the power of polymorphism to obtain a reference-to-base.

ostream& operator<<(ostream& TextBookOutput, const TextBook& printTextBook) {
    return TextBookOutput << "TextBook: " << static_cast<const Book&>(printTextBook) << "Grade:" << printTextBook.grade;
}
几度春秋 2024-11-12 13:52:08
return TextBookOutput << static_cast<Book const &>(printTextBook) << ...
return TextBookOutput << static_cast<Book const &>(printTextBook) << ...
云朵有点甜 2024-11-12 13:52:08

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

问题是这样的,考虑一下你已经拥有的东西:
<代码>

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";
}

Everything will go as expected if you use it like this:

Book book;
TextBook textBook;
cout << book << "\n";     // prints out: Book: XYZ
cout << textBook << "\n"; // prints out: TextBook: XYZ 


That is because the compiler will correctly determine the type of the book during compilation time (statically).

现在考虑另一种情况:
<代码>

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);
}

As others pointed out, you should use downcasting to achieve what you are asking for. But I think you should consider a different approach as well: What you are doing right now is mixing static and dynamic polymorphism, this often isn't a good idea (which usually only manifests itself later on).

Here is the problem, consider what you've got already:

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";
}


Everything will go as expected if you use it like this:

Book book;
TextBook textBook;
cout << book << "\n";     // prints out: Book: XYZ
cout << textBook << "\n"; // prints out: TextBook: XYZ 


That is because the compiler will correctly determine the type of the book during compilation time (statically).

Now consider this other case:

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

This is because the compiler can't know what higher type it is, it can be Book, TextBook or ChildrensBook. This can only be determined during runtime (dynamically) using virtual functions etc.

So in case you consider utilizing dynamic polymorphism I would prefer this approach:

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);
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文