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.
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;
}
return TextBookOutput << static_cast<Book const &>(printTextBook) << ...
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);
}
Related
I'm trying to understand how to properly overload the "<<" operator so that I can use
std::cout << my_object;
to print useful debug messages. In particular, I need to have an implementation of << for each of my subclasses, so I'm declaring << to be virtual in the superclass.
Right now I'm stuck with the following piece of code
#include <iostream>
using namespace std;
class Shape {
public:
virtual ~Shape() { };
virtual ostream& operator<<(std::ostream &strm) = 0;
};
class Square : public Shape {
int size;
public:
Square() { size = 10; }
~Square() { }
ostream& operator<<(std::ostream &strm) {
return strm << "a square with size " << size;
}
};
int main() {
Square *my_square = new Square();
cout << "my_square is " << my_square << "\n";
}
which (I think) should be working, but doesn't. What I get when using "<<" is that the pointer value of my_square gets printed, rather than the result of the overloaded << .
$ ./a.out
my_square is 0xcacc20
What am I missing here?
operator<< can't be a member function. This is because of the order of the arguments. The stream has to come first.
When calling an overloaded operator, such as:
os << object;
the compiler will attempt to look up both
os.operator<<(object);
and
operator<<(os, object);
(The rules for this can be rather complex, I won't attempt to describe them here.)
Because the stream always comes on the left, your member function will never be found, since it would have to be called as:
object.operator<<(os);
You need to write a free function like:
ostream& operator<<(std::ostream &strm, Square const& square) {
return strm << "a square with size " << square.size();
}
(where Square::size() returns the size member).
Then you need to remember to dereference your pointer too:
std::cout << *my_square << '\n';
Although I see no reason to be dynamically allocating my_square in this example anyway. Just stick it on the stack as a local variable.
If the aim here is ultimately to be able to print any Shape&, and have the printed output follow the "real" type, you would need to create:
virtual std::ostream& print(std::ostream&) const = 0;
in the Shape base class, and override it in each derived class, then have a free function:
std::ostream& operator<<(std::ostream& os, Shape const& shape)
{
return shape.print(os);
}
It is often advised to make all binary operators on your type non-member functions, so that both arguments are treated equally, and the operation remains commutative. See Scott Meyers, Effective C++ (3rd Edition), Item 24, (or find a summary online).
As noted by others, the problem is that operator << can't be member function (because of the order of arguments). The canonical way to do this is to have operator <<(const Shape&) call a virtual function in Shape
class Shape {
friend ostream& operator<<(std::ostream& str, const Shape& shape);
virtual void do_print(ostream& str) = 0;
public:
virtual ~Shape() { };
};
ostream& operator<<(std::ostream& str, const Shape& shape) {
shape.do_print(str);
return str;
}
Note that it is legal to have do_print be private, even though it is going to be (must be) overridden by derived classes. You could make it protected though if you like.
What am I missing here?
You have created operator which will get you class as a first argument and stream as the second.
my_square << std::cout;
I'd create free function and to make it dynamic I'd call some virtual method in it
I have written a program for implementation of stack. And I have one display function in it.
This is how I wrote display function at first:
template <class t>
void Mystack<t>::display()
{
for (int i = 0; i <= top; i++)
{
std::cout << input[i] << " ";
}
}
Then I was suggested by developers to write a display function to be more generic. So I wrote display function as:
template <class T>
void Mystack<T>::display(std::ostream &os) const
{
for (int i = 0; i <= top; i++)
{
os << input[i] << " ";
}
}
As per my understanding the benefit of writing above function is that now I have a generic display function which I can use to display data to console or to a file too.
Question 1: Is my understanding correct?
Now another suggestion is to write function something like:
template <typename T>
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d) {
d.display(s);
return s;
}
Question 2: What is the benefit of having above display function? What exactly will I be able to achieve by having above display function?
For question 1, your understanding is correct, but the real improvement comes from question 2's suggestion of writing:
template <typename T>
friend std::ostream& operator<<(std::ostream&, Mystack<T> const& );
That will let anybody stream objects of your type in the same way they would stream anything else:
std::cout << "Hi, my stack is " << stack << ", it has size " << stack.size();
to any stream they want:
some_file << "Result of computation is: " << stack;
std::cerr << "Error, invalid stack: " << stack << ", expected: " << some_other_thing;
Firstly - yes. By taking the std::ostream& parameter, you can output to any derived stream too, like std::ofstream, or std::cout, std::cerr.
Using operator<< allows you to, use that operator. Consider:
mystack<int> stackOfInts;
//...
std::cout << "Stack contents:" << std::endl << stackOfInts << std::endl;
It's just more idiomatic than a 'standard' function call.
Returning the stream allows the chaining of the operator, as in the above example. The chaining is effectively passing the result of a call to operator<< into another one:
operator<<( operator<<("Stack contents:", std::endl), stackOfInts ) );
If this overloaded call doesn't also return an std::ostream&, then there is no way to do:
operator<<( resultOfAbove, std::endl );
Declaring the function a friend allows its definition to use private members. Without this, you would have to do something like write a public getter for each private member.
Both display function are basically the same. The different is the way you call the function.
With first function, you call function in usual way:
std::cout<<"This is MyStack (with first method): ";
m.display(std::cout); //function call
std::cout<<std::endl;
With second function, you call function with operator "<<":
std::cout<<"This is MyStack (with second method): "
<<m //function call
<<std::endl;
But I personally prefer the second one. Since it's more familiar to me.
As with regard to Question 2, this is the way to go if you have a base class and lots of derived classes, and want to write operator<< only once, in the base class. Then, if you declare the display() function as virtual along your class hierarchy, you can choose at runtime the correct display function. That is, if you have something like
Derived foo;
std::cout << foo;
then Base::operator<< will call the Derived::display(), because it is marked as virtual and foo is passed by reference. This is the way to go when you have a class hierarchy and don't want to overload operator<< for each derived class.
This is a common trick in avoiding code duplication. See
Making operator<< virtual?
on StackOverflow for more details.
Does std::basic_ostream have an overload of operator << that accepts a std::basic_string object? I'm reading cppreference and there doesn't seem to be one listed.
Imagine you create your own class called Car which contains licence plates number, model/power of the engine, and bunch of other information. Now, imagine you want to provide nice way to print your car information into the file, or into the screen.
If you want to use basic_ostream overload, you have no luck, since there is no overload for your class defined. You may provide print_into_ostream method, or some other clever trick, but you've just realized that std::string also doesn't have the appropriate overload, and you still can do cout << myStr;. After a quick search, you find a solution that is applied into the std::string, and you can use it in your class like this:
class Car
{
std::string licence_plate, engine;
public:
// ... other here ...
friend ostream& operator<<(ostream& os, const Car& c);
};
ostream& operator<<(ostream& os, const Car& c)
{
os << c.licence_plate << "-" << c.engine;
return os;
}
And now you can use
cout << myCarObject << endl;
as with any built-in type.
std::string uses the same approach, and you can find documentation here.
There are non-member operators defined in the std namespace. See cppreference.
If you want to print an object of your class A, you overload << operator like this:
ostream & operator << (ostream & os, A &a)
{
os << a.data_member;
}
In the same fashion in the std namespace there is an overloaded operator that prints object of class string.
I've come across functions that, rather than overloading the operator << to use with cout, declare a function that takes an ostream and returns an ostream
Example:
#include <iostream>
class A {
private:
int number;
public:
A(int n) : number(n) {}
~A() {}
std::ostream& print(std::ostream& os) const;
friend std::ostream& operator<<(std::ostream& os, const A a);
};
An example of implementation:
std::ostream& A::print(std::ostream& os) const {
os << "number " << number;
return os;
}
std::ostream& operator<<(std::ostream& os, const A a) {
os << "number " << a.number;
return os;
}
Now if I run this I can use the different functions in different situations.. E.g.
int main() {
A a(1);
std::cout << "Object."; a.print(std::cout);
std::cout << "\n\n";
std::cout << "Object." << a;
std::cout << "\n\n";
return 0;
}
Output:
Object.number 1
Object.number 1
There doesn't seem to be a situation where the print function would be needed since you could only use separately or in the beginning of a "cout chain" but never in the middle or end of it which perhaps makes it useless. Wouldn't it (if no other use is found) be better off using a function "void print()" instead?
It would make sense where an inheritance hierarchy comes in to play. You can make the print method virtual, and in the operator for the base class, delegate to the virtual method to print.
It would make a lot more sense if operator<<() actually looked like
std::ostream& operator<<(std::ostream& os, const A a) {
return a.print(os);
}
Then operator<<() wouldn't need to be a friend.
A function that can be used as the start of a cout chain certainly sounds more useful than one that can't, all other things being equal.
I've implemented several functions with signatures like you describe because operator<< is only one name, and sometimes I need to have objects streamed in multiple different ways. I have one format for printing to the screen, and another format for saving to a file. Using << for both would be non-trivial, but choosing a human-readable name for at least one of the operations is easy.
The use of operator<< assumes that there is only one sensible way to print data. And sometimes that is true. But sometimes there are multiple valid ways to want to output data:
#include <iostream>
using std::cout; using std::endl;
int main()
{
const char* strPtr = "what's my address?";
const void* address = strPtr;
// When you stream a pointer, you get the address:
cout << "Address: " << address << endl;
// Except when you don't:
cout << "Not the address: " << strPtr << endl;
}
http://codepad.org/ip3OqvYq
In this case, you can either chose one of the ways as the way, and have other functions (print?) for the rest. Or you can just use print for all of them. (Or you might use stream flags to trigger which behavior you want, but that's harder to set up and use consistently.)
class object_1
{
public:
...
friend ofstream& operator<<(ofstream &out, const object_1 &obj_1);
friend object_2;
private:
char *pCh_mem1;
char *pCh_mem2;
int *pInt_mem1;
int *pInt_mem2;
};
class object_2
{
public:
...
friend ofstream& operator<<(ofstream &out, const object_2 &obj_2);
friend object_1;
};
Object1's implementation file is typical. Ctor, Dtor and some methods. I havent posted the method declarations in the header because their irrelevant to my problem.
It is very important that I discuss the objects lifetime.It is something that I really need to understand. Whats happening is that the operator overload function is then invoked when I call object_2 in main. So then the operator overload function is called:
ostream& operator<<(ostream& out, const object_2& obj_2)
{
object1::display(out) //Calls method display in object1's I.F.
return out;
}
here we are:
void object_1::display(std::ostream &out)
{
out << left << setw(28) << "Person" << setw(20) << "Place" ;
out << right << setw(5) << "Thing" << setw(5) << "Idea" << endl;
out << left << setw(28) << "----" << setw(20) << "--------" ;
out << right << setw(5) << "----- " << setw(5) << "------" << endl;
}
At the top of the implementation file is the IOMANIP library. So setw(X) and everything are defined. Im getting 0's all prinited to the console. Did my object go out of scope? I think so because when i do all these before I need to, it works fine. That is, when I call this function n e where else than in the body of the operator overload it works. I think because the object is redeclared:
ostream& operator<<(ostream& out, const object_2& obj_2);
then after I print the formatting method I need to print the information that was passed in from main to the first object's ctor; object_1. When that happens we are in the overload function which is similar and its the same implementation file. Im calling both methods from the overload in the second objects overload function:
ostream& operator<<(ostream& out, const object_1& obj_1)
{
out << obj_1.pCh_mem1 << obj_1.pCh_mem2;
return out;
}
// main
object_2 obj_2(4);
static void method1()
{
//do stuff
}
static void method2()
{
//do stuff
}
static void method3()
{
//do stuff
}
int main(void)
{
method1();
method2();
method3();
cout << obj_2;
return 0; // and such
}
Once objc_2 is called like u see above, the operator overload for object2's class will then be called. I cant use any of my private members because its an illegal operatation. I guess my questions is. How can i print my private members from object1 in my object2's operator overloading function? static_cast's? I have a random snippet from main, Its complicated and I cant alter it.
ostream& operator<<(ostream& out, const object_2& obj_2)
{
object1::display(out) //Calls method display in object1's I.F.
return out;
}
What i've been trying to do, like you see above is call the other objects methods, and get the info from their. But that info is all NULL!! Im hopping from one I.F. to the next and its all NULL!!
AFAICT, object_1 and object_2 are unrelated classes (except that they are friends). So an object_2 does not have any state relevant to an object_1.
Therefore, when you try to print an object_2 as if it were an object_1, this cannot possibly work. It is surprising that this call works at all:
ostream& operator<<(ostream& out, const object_2& obj_2)
{
object1::display(out) //Calls method display in object1's I.F.
return out;
}
since there is no object_1 around here for which a method can be called (but then, you probably didn't mean this to be real code, since it's missing a semicolon also).
It's not completely clear what you want to achieve. Maybe you want object_2 to inherit from object_1, so that any object_2 will also have the members pCh_mem1 etc? Maybe you want a member of object_2 to be an object of type object_1?
ostream& operator<<(ostream& out, const object_2& obj_2)
{
out << object_1[thatIndexThatIstoreditAt]
return out;
}
I need to write a few reports on this stuff. =)