Online Book Reader

Home Category

Professional C__ - Marc Gregoire [321]

By Root 1066 0
in printArray() only because arr is const. If arr were not const, the non-const operator[] would be called, despite the fact that the result is not modified.

Non-Integral Array Indices

It is a natural extension of the paradigm of “indexing” into a collection by providing a key of some sort; a vector (or in general, any linear array) is a special case where the “key” is just a position in the array. Think of the argument of operator[] as providing a mapping between two domains: the domain of keys and the domain of values.

Thus, you can write an operator[] that uses any type as its index. This type does not need to be an integer type. This is done for the STL associative containers, like std::map, which are described in Chapter 12.

For example, you could create an associative array, in which you use string keys instead of integers. Here is the definition for an associative array class that stores ints:

class AssociativeArray

{

public:

AssociativeArray();

virtual ~AssociativeArray();

int& operator[](const std::string& key);

const int& operator[](const std::string& key) const;

protected:

// Implementation details omitted

};

Code snippet from AssociativeArray\AssociativeArray.h

Implementing this class would be a good exercise for you. You can also find an implementation of this class in the downloadable source code for this book on www.wrox.com.

You cannot overload the subscripting operator to take more than one parameter. If you want to provide subscripting on more than one index, you can use the function call operator explained in the next section.

OVERLOADING THE FUNCTION CALL OPERATOR


C++ allows you to overload the function call operator, written as operator(). If you write an operator() for your class, you can use objects of that class as if they were function pointers. You can only overload this operator as a non-static method in a class. Here is an example of a simple class with an overloaded operator() and a class method with the same behavior:

class FunctionObject

{

public:

int operator() (int inParam); // Function-call operator

int doSquare(int inParam); // Normal method

};

//Implementation of overloaded function-call operator

int FunctionObject::operator() (int inParam)

{

return doSquare(inParam);

}

// Implementation of normal method

int FunctionObject::doSquare(int inParam)

{

return inParam * inParam;

}

Code snippet from Functors\Functors.cpp

Here is an example of code that uses the function-call operator, contrasted with the call to a normal method of the class:

int x = 3, xSquared, xSquaredAgain;

FunctionObject square;

xSquared = square(x); // Call the function-call operator

xSquaredAgain = square.doSquare(x); // Call the normal method

Code snippet from Functors\Functors.cpp

An object of a class with a function call operator is called a function object, or functor, for short.

At first, the function call operator probably seems a little strange. Why would you want to write a special method for a class to make objects of the class look like function pointers? Why wouldn’t you just write a function or a standard method of a class? The advantage of function objects over standard methods of objects is simple: These objects can sometimes masquerade as function pointers. You can pass function objects as callback functions to routines that expect function pointers, as long as the function pointer types are templatized. This is discussed in Chapter 13.

The advantages of function objects over global functions are more intricate. There are two main benefits:

Objects can retain information in their data members between repeated calls to their function-call operators. For example, a function object might be used to keep a running sum of numbers collected from each call to the function-call operator.

You can customize the behavior of a function object by setting data members. For example, you could write a function object to compare an argument to the function against a data member. This data member could be configurable so that the object could be customized for whatever

Return Main Page Previous Page Next Page

®Online Book Reader