Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng].pdf
Скачиваний:
84
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

Chapter 23: A New Assignment Operator, Should You Decide to Accept It 311

This is what enables the programmer to write the following:

d2 = d1 = 2.0

fn(d2 = 3.0); // performs the assignment and passes the // resulting value to fn()

The value of the assignment d1 = 2.0 (2.0) and the type (double) are passed to the assignment to d2. In the second example, the value of the assignment d2 = 3.0 is passed to the function fn().

The second detail is that operator=() was written as a member function. The left-hand argument is taken to be the current object (this). Unlike other operators, the assignment operator cannot be overloaded with a nonmember function.

Protecting the Escape Hatch

Providing your class with an assignment operator can add considerable flexi­ bility to the application code. However, if this is too much work or if you don’t want C++ to make copies of your object, overloading the assignment operator with a protected function will keep anyone from accidentally making an unau­ thorized member-by-member shallow copy, as illustrated here:

class Name

{

//...just like before...

protected:

// copy constructor Name(Name&) {} //assignment operator

Name& operator=(Name& s) { return *this; }

};

With this definition, assignments such as the following are precluded:

void fn(Name &n)

{

Name newN;

newN = n; //generates a compiler error - //function has no access to op=()

}

This copy protection for classes saves you the trouble of overloading the assignment operator but reduces the flexibility of your class.

If your class allocates resources such as memory off the heap, you must either write a satisfactory assignment operator and copy constructor or make both protected to preclude the default provided by C++ from being used.

312 Part V: Optional Features

Chapter 24

Using Stream I/O

In This Chapter

Performing input/output

Rediscovering stream I/O as an overloaded operator

Using stream file I/O

Using stream buffer I/O

Going behind the scenes with manipulators

Programs appearing before this chapter read from the cin input object and output through the cout output object. Perhaps you haven’t really

thought about it much, but this input/output technique is a subset of what is known as stream I/O.

In this chapter, I describe stream I/O in more detail. I must warn you that stream I/O is too large a topic to be covered completely in a single chapter — entire books are devoted to this one topic. Fortunately for both of us, there isn’t all that much that you need to know about stream I/O in order to write the vast majority of programs.

How Stream I/O Works

Stream I/O is based on overloaded versions of operator>>() and operator<<(). The declaration of these overloaded operators is found in the include file iostream, which are included in all the programs beginning in Chapter 1. The code for these functions is included in the standard library, which your C++ program links with.

The following code shows just a few of the prototypes appearing in iostream:

//for input we have:

istream& operator>>(istream& source, char *pDest);

istream& operator>>(istream& source, int &dest); istream& operator>>(istream& source, char &dest);

314 Part V: Optional Features

//...and so forth...

//for output we have:

ostream& operator<<(ostream& dest, char *pSource); ostream& operator<<(ostream& dest, int source); ostream& operator<<(ostream& dest, char source); //...and so it goes...

When overloaded to perform I/O, operator>>() is called the extractor, and operator<<() is called the inserter. The class istream is the basic class for input from a file or a device like the keyboard. C++ opens the istream object cin when the program starts. Similarly, ostream is the basis for file output. cout is a default ostream object.

Take a detailed look at what happens when you write the following code, which is named DefaultStreamOutput and found on this book’s CD-ROM:

// DefaultStreamOutput #include <iostream> using namespace std;

void fn(ostream& out)

{

out << “My name is Stephen\n”;

}

int main(int nNumberofArgs, char* pszArgs[])

{

fn(cout);

system(“PAUSE”); return 0;

}

The program passes cout to the function fn(). fn() applies the << operator, otherwise known as operator<<(). Thus, C++ determines that the best match is the operator<<(ostream&, char*) function. C++ generates a call to this function, the so-called char* inserter, passing the function the ostream object cout and the string “My name is Randy\n” as arguments. That is, it makes the call operator<<(cout, “My name is Randy\n”). The char* inserter func­ tion, which is part of the standard C++ library, performs the requested output.

The ostream and istream classes form the base of a set of classes that con­ nects the application code with the outside world, including input from and output to the file system. How did the compiler know that cout is of class ostream? This and a few other global objects are also declared in iostream. h. A list is shown in Table 24-1. These objects are constructed automatically at program startup, before main() gets control. Subclasses of ostream and istream are used for input and output to files and internal buffers.