Операторы в производном классе переопределяются, но все еще используют родительский класс - PullRequest
3 голосов
/ 09 мая 2011

В частности, я хотел бы иметь возможность использовать ostream operator << в двух производных классах от базового класса.

Программа, которую я создаю, должна распечатывать информацию о товарах для различных "товаров" в "виртуальном магазине". Среди продуктов есть два разных вида книг. Каждая из этих книг должна иметь свои собственные:

ID number
Author
NumberOfPages
Year

Кроме того, тип ChildrensBook должен содержать минимальный возраст, а TextBook - класс.

Я определил класс Book и вывел из него классы ChildrensBook и TextBook. Мой вопрос касается использования ostream operator << для распечатки информации.

Могу ли я определить универсальную функцию << в классе Book, которая будет распечатывать всю информацию, общую для обоих производных классов, и затем обращаться к ней в переопределении << в производных классах? </p>

Например,

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

Итак, я думаю, что мой вопрос можно сформулировать так: могу ли я вызвать родительский оператор из дочернего оператора, и если да, какой синтаксис я использую?

Другая идея, которая пришла мне в голову, - написать функцию для дочернего элемента, которая использует родительский оператор печати, а затем вызвать эту функцию из дочернего оператора печати. Это означало бы, что я не пытался вызвать оператор при его переопределении, но по-прежнему требует использования родительского оператора и отдельного переопределения дочернего оператора.

Ответы [ 3 ]

4 голосов
/ 09 мая 2011

Конечно.

У вас есть оператор на Book с, так что используйте его. Вы можете вызвать его, дав ему ссылку на книгу, и вы можете использовать силу полиморфизма для получения ссылки на базу.

ostream& operator<<(ostream& TextBookOutput, const TextBook& printTextBook) {
    return TextBookOutput << "TextBook: " << static_cast<const Book&>(printTextBook) << "Grade:" << printTextBook.grade;
}
0 голосов
/ 09 мая 2011

Как отмечали другие, вы должны использовать даункинг, чтобы достичь того, о чем вы просите.Но я думаю, что вы должны рассмотреть и другой подход: то, что вы делаете сейчас, это смешивание статического и динамического полиморфизма, это часто не очень хорошая идея (которая обычно проявляется толькосам по себе позже)тип книги во время компиляции (статически).

Теперь рассмотрим другой случай: Book * textBook = new TextBook(); cout << *textBook << "\n"; // prints out: Book: XYZ !

Это потому, что компилятор не может знать, какой это более высокий тип, он можетбыть книгой, учебником или детской книгой.Это может быть определено только во время выполнения (динамически) с использованием виртуальных функций и т. Д.

Поэтому, если вы решите использовать динамический полиморфизм, я бы предпочел такой подход: 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); }

0 голосов
/ 09 мая 2011
return TextBookOutput << static_cast<Book const &>(printTextBook) << ...
...