Hello again! In this video, we are going to look at printing out class member data.
So far, we have been using a print() member function, which sends the data members to cout.
We cannot use the left shift operator because that does not compile.
And we get all these horrible templates error messages.
The problem is there is no left shift operator which takes a Test object as one of its arguments,
and there is no way to convert to it.
So if we use the print() member function that works, but it is rather limited because we can only use it
with cout.
Perhaps we can make this more general, so we can use it with any output stream.
So now we have the same class again, but this time we have added an output stream as the argument to the
print() member function. So we can now send the data members to the output stream.
And this will work for any type of output stream, regardless of whether it is iostream, fstream
or stringstream.
We need to pass the argument by reference for two reasons.
First of all, because the function is going to modify the stream. It is going to push data onto it
and change its state, and also because ostreams cannot be copied.
So we cannot pass this by value.
And then, in the main() function, we pass the stream as argument.
So if we want to
display data, we pass cout as the arguments.
Or alternatively, we can open a file, and use the file stream as the argument to print().
So there we are, we get the output and also... We get the file output as well.
So that does work, but it would be nice if we could use the left shift operator, so our code would
look like all the other code that uses the built-in and the library types. To do that, we need to understand
how the library and built-in types work with the left shift operator.
And the answer is that the core language and the standard library provide overloads of that operator,
which take that type as the second argument.
For example, if we send an int to standard output, that will result in the left shift operator being
called with cout and i as the arguments.
And this is a binary operator, so it cannot be a member function of ostream.
We are allowed to chain together calls to this operator. So we can send multiple objects to the same
stream in a single statement, like that.
And this will actually result in a pair of nested function calls.
So first, it is going to call the operator, with cout and i as the arguments, to push i into the stream.
And then the return value from that will be used as the stream, and j will be pushed onto that stream.
So this operator call must return cout. Again, that must be by reference, not by value.
So the prototype is going to operator left shift, which takes an ostream by reference and the
data type, and returns the stream by reference.
I have implemented this operator for our class.
This is outside the class,
of course. It is not a member function of the class or the ostream.
It takes the ostream and the Test object as argument, by reference.
It calls the print() member function of the Test class, with the ostream as the argument, and then
returns the same stream.
So if we call it repeatedly, it will still work.
And then in the main() function, we can use this just like we do with any other object of built-in types
or library types.
And it works with files as well.
Okay, so that is it for this video.
I will see you next time.
Until then, keep coding!