In this class we take a close look at some uses for constructors
and examine the C++ concept of I/O streams.


Copy constructor for Rational

// in the class definition (rational.h) class Rational { private: ...... public: ...... Rational (const Rational&); ..... }; // -------------------------------------------- // the implementation -- rational.C Rational::Rational (const Rational& value) : num (value.num), den (value.den) { // no code } QUESTION: Why MUST the argument to the copy constructor be a reference?

Constructors used for initialization

It's important to understand the difference between initialization and assignment. Why??? -- different functions are called -- constructor or operator = copy constructors are used whenever a new object is created and initialized to an existing object of the same kind * for creating copies of parameters for call-by-value * for creating temporary objects for return-by value * when explicitly called to initialize a new object from an existing object Consider the following declarations -- what constructor(s) is(are) called? Rational a; Rational b(5); Rational c (3, 7); Rational d = c; Rational e = Rational (1, 2); Rational f = 6;

Constructors for type conversion

Sometimes it is necessary for the compiler to convert from one data type to another. Example -- function f (double) is called as f(6). The compiler implicitly changes the 6 to 6.0 and calls f as f(6.0). We can do the same thing with classes. We can provide the means for the compiler to change other data types into Rational objects. Constructors with a single argument such as Rational (int) are used for conversion Automatic type conversion using Rational(int) will be used 1. when you initialize a Rational object with an Int Rational x = 7; 2. when you assign an int to a Rational a = 6; 3. when you pass an int to a function expecting Rational that's how z = y + 7; works 4. when a function that's declared to return Rational tries to return int QUESTION: Can we convert Rational to int, double, etc. ANSWER: Yes, if we provide the mechanism (not constructors) to do so. See text pages 271 & 272 for discussion on how to do this.

I/O streams

No more printf, or output specifications C++ uses the Unix concept of streams for all I/O. What is a stream? classes and instances in <iostream.h> ostream -- a class for output stream istream -- a class for input stream cout, cerr -- instances of ostream for output (replace stdout, stderr) cin -- instance of istream for input (replaces stdin) operator << -- insertion operator for output operator >> -- extraction operator for input operators are already overloaded for built-in types ostream& operator<< (ostream& out, const& int) The reference returned is to the ostream argument we can overload these too
// a simple example of input/output from/to the console #include <iostream.h> main () { int i; double f = 5.3; // get a value for i from cin cin >> i; // output values of i and f cout << i; cout << " "; cout << f; cout << endl; } Questions: 1. why don't we need address of 'i' in "cin >> i;"? 2. output could also be written as cout << i << " " << f << endl; Why is this possible? Manipulators -- flush, endl, others (width, fill, precision,...) see iomanip.h for details

Overloading ouput operator<<

It would be nice to be able to output any user-defined object using the output operator <<. C++ allows us to do this with operator overloading The first parameter to each operator<< function in the C++ library is a reference to an "ostream". This is done to allow us to cascade the << operator like we did in the example above. Therefore, whenever we overload operator<<, our return type must also be ostream&. Which ostream do we return a reference to?? -- the one that was passed in. The function operator<< is typically defined to be a friend function. class Rational { private: int num, den; public: . . . . friend ostream& operator<< (ostream& out, const Rational& r); . . . . } ostream& operator<< (ostream& out, const Rational& r) { out << r.num << "/" << r.den; return out; } Now when we can write Rational X(4,5); cout << X; the output is 4/5 QUESTION: Why can't operator<< be a member function of Rational (or any other object)? ANSWER: QUESTION: What is the general form of the prototype for operator<< for any class ABC? ANSWER: QUESTION: Why didn't we output an endl in our operator<< function? ANSWER: