Function-Object Classes with State

Like any other class, a function-object class can have additional members aside from operator(). Function-object classes often contain data members that are used to customize the operations in the call operator.

As an example, we’ll define a class that prints a string argument. By default, our class will write to cout and will print a space following each string. We’ll also let users of our class provide a different stream on which to write and provide a different separator. We can define this class as follows:

class PrintString {
public:
    PrintString(ostream &o = cout, char c = ' '):
        os(o), sep(c) { }
    void operator()(const string &s) const { os << s << sep; }
private:
    ostream &os;   // stream on which to write
    char sep;      // character to print after each output
};

Our class has a constructor that takes a reference to an output stream and a character to use as the separator. It uses cout and a space as default arguments (§ 6.5.1, p. 236) for these parameters. The body of the function-call operator uses these members when it prints the given string.

When we define PrintString objects, we can use the defaults or supply our own values for the separator or output stream:

PrintString printer;   // uses the defaults; prints to cout
printer(s);            // prints s followed by a space on cout
PrintString errors(cerr, ' '),
errors(s);             // prints s followed by a newline on cerr

Function objects are most often used as arguments to the generic algorithms. For example, we can use the library for_each algorithm (§ 10.3.2, p. 391) and our PrintString class to print the contents of a container:

for_each(vs.begin(), vs.end(), PrintString(cerr, ' '));

The third argument to for_each is a temporary object of type PrintString that we initialize from cerr and a newline character. The call to for_each will print each element in vs to cerr followed by a newline.


Exercises Section 14.8

Exercise 14.33: How many operands may an overloaded function-call operator take?

Exercise 14.34: Define a function-object class to perform an if-then-else operation: The call operator for this class should take three parameters. It should test its first parameter and if that test succeeds, it should return its second parameter; otherwise, it should return its third parameter.

Exercise 14.35: Write a class like PrintString that reads a line of input from an istream and returns a string representing what was read. If the read fails, return the empty string.

Exercise 14.36: Use the class from the previous exercise to read the standard input, storing each line as an element in a vector.

Exercise 14.37: Write a class that tests whether two values are equal. Use that object and the library algorithms to write a program to replace all instances of a given value in a sequence.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.206.225