An input operator is predefined for all built-in C++ types. If you create a class type and want to read input from a file or the standard input device into objects of that class type, you need to define an input operator for that class's type. You define an istream input operator that has the class type as its second argument. For example:
myclass.h
#include <iostream.h> class PhoneNumber { public: int AreaCode; int Exchange; int Local; // Copy Constructor: PhoneNumber(int ac, int ex, int lc) : AreaCode(ac), Exchange(ex), Local(lc) {} //... Other member functions };
istream& operator>> (istream& aStream, PhoneNumber& aPhoneNum) { int tmpAreaCode, tmpExchange, tmpLocal; aStream >> tmpAreaCode >> tmpExchange >> tmpLocal; aPhoneNum=PhoneNumber(tmpAreaCode, tmpExchange, tmpLocal); return aStream; }
The input operator must have the following characteristics:
You can define the code performing the actual input any way you like. In the above example, input is accomplished for the class type by requesting input from the istream object for all data members of the class type, and then invoking the copy constructor for the class type. This is a typical format for a user-defined input operator.
Be careful not to use the cin stream as the input stream when you define an input operator for a class type, unless this is what you really want to do. In the example above, if the line
aStream >> tmpAreaCode >> tmpExchange >> tmpLocal;
is rewritten as:
cin >> tmpAreaCode >> tmpExchange >> tmpLocal;
the input operator functions identically, when you use statements in your main program such as cin >> myNumber. However, if the stream requesting input is not the predefined stream cin, then redefining an input operator to read from cin will produce unexpected results. Consider how the following code's behavior changes depending on whether cin or aStream is used as the stream in the input statement within the input operator defined above:
#include <iostream.h> #include <fstream.h> #include "myclass.h"
void main() { PhoneNumber addressBook[40]; fstream infile("address.txt",ios::in); for (int i=0;i<40;i++) infile >> addressBook[i]; // does this read from "address.txt" // or from standard input? //... }
In the original example, the definition of the input operator causes the program to read input from the provided istream object (in this case, the fstream object infile). The input is therefore read from a file. In the example that uses cin explicitly within the input operator, the input that is supposedly coming from infile according to the input statement infile >> addressBook[i] actually comes from the predefined stream cin.
You can display prompts for individual data members of a class type within the input operator definition for that type. For example, you could redefine the PhoneNumber input operator shown above as:
istream& operator>> (istream& aStream, PhoneNumber& aPhoneNum) { int tmpAreaCode, tmpExchange, tmpLocal; cout << "Enter area code: "; aStream >> tmpAreaCode; cout << "Enter exchange: "; aStream >> tmpExchange; cout << "Enter local: "; aStream >> tmpLocal; aPhoneNum=PhoneNumber(tmpAreaCode, tmpExchange, tmpLocal); return aStream; }
You may be tempted to do this when you anticipate that the source of all input for objects of a class will be the standard input stream cin. Avoid this practice wherever possible, because a program using your class may later attempt to read input into an object of your class from a different stream (for example, an fstream object attached to a file). In such cases, the prompts are still written to cout even though input from cin is not consumed by the input operation. Such an interface does not prevent programs from using your class, but the unnecessary prompts may puzzle end users.
You can use the same techniques for output to other output streams as for output to the predefined output streams. The only difference is that, for other output streams, your program must define the stream. Assuming you have defined a stream attached to a file opened for output, and have called that stream myout, you can write to that file through its stream, by specifying the stream's name instead of cout, cerr or clog:
// assume the output file is associated with stream myout int a,b; myout << a << b;