Borland Online And The Cobb Group Present:


July, 1994 - Vol. 1 No. 7

C++ Language Basics - Overloadingthe function call operator

As you begin defining your own classes using Borland C++, you'll probably define member functions­­functions that belong to your classes. In addition, you may want to add operator overloading­­support for various operators in your classes.

For example, you may want to use the pre-increment (++x) or post-increment (x++) operator with objects of one of your classes. The meaning of these operations will be fairly obvious­­they'll typically behave the same with your classes as they do with the built-in types (int, char, int*, and so on).

However, understanding what happens when you overload the operator () function call operator for a class is more difficult because there's no definition for using this operator with variables of the built-in types. In this article, we'll show you how to overload the function call operator in your own classes.

What does the function call operator do?

Since there isn't a predefined meaning for operator (), you're free to implement any behavior that seems appropriate. In addition, you can specify any return type and as many arguments as you'd like when you define operator (). Unfortunately, a number of questions come to mind.

Why would you overload operator ( )?

You'll want to overload operator () in three instances: single-function classes, array subset subscripting, and multidimensional array indexing. A single-function class has only one function (besides the constructors and destructors) that the user will call in normal situations. For example, you might want to create a number-averaging class that maintains a running average of a series of numbers. For this class, you could define operator () to accept a new number as the only argument and return the resulting average.

When you use operator () to implement subset subscripting, you're specifying that you want to retrieve multiple items from the array. A common form of this is an operator () function that retrieves a substring from a string class based on position and length.

For a multidimensional array class, you can use operator () to implement subscripting. One reason to do this is that the syntax you use to call operator () is similar to that of the subscript operator, operator [].

How do you call operator ( )?

You call operator () the same way you specify an element of an array with the subscript operator. For example, if you define a four-dimensional array class FourDArray and create an object named fourD, you can access a specific element of the array with the statement

fourD(4,2,2,22)

If you're calling operator () on a single function class and you've declared it to take no parameters, you'll use the statement

item()

to call operator () on the object named item.

How do you overload operator ( )?

Perhaps the most confusing aspect of defining operator () is the syntax of declaring the operator itself. Inside a class declaration, the syntax

int operator () ();

declares operator () to accept no parameters and return an integer value. In this statement, the first set of parentheses specifies the name of the operator, and the second set specifies the argument list for the overloaded operator.

If you want to pass one or more parameters to operator (), you'll add the argument types and identifiers within the second set of parentheses. To declare operator () for the number-averaging class described earlier, you might write

float operator () (float newNumber);

Therefore, the statement

avg(86.4)

is equivalent to

avg.operator () (86.4)

as far as the compiler is concerned, although it's unlikely that you'd see anyone use the second form.

Finally, you can define operator () as a nonstatic member function only. It can't be a static function, because you must call it with an instance of its class. (This is similar to the idea that you must first have an array of characters before you can use operator [] to retrieve an element of the array.)

An average example

To put operator () into action, let's create a program that calculates a running average of floating point values. To begin, launch the Borland C++ 3.1 Integrated Development Environment (IDE) for DOS. (This program works with Borland C++ 4.0 as well.)

When the IDE's desktop appears, choose New from the File menu to open an editor window for a new source file. When the new window appears, enter the code from Listing A.


Listing A: AVERAGER.CPP

#include <iostream.h>

class Averager
{
  public:
    Averager() {
      total = 0;
      itemCount = 0; }
    float operator () (float item) {
      total += item;
      ++itemCount;
      return total/itemCount; }
  private:
    float total;
    int   itemCount;
};

int main()
{
  Averager avg;

  float newValue = 0;
  do {
    cout << "Enter new value ";
    cin >> newValue;
    cout << "Average is " << avg(newValue);
    cout << endl;
  } while (newValue != -1);

  return 0; 
}

When you finish entering the code, choose Save from the File menu. In the Save File As entry field of the Save File As dialog box, enter AVERAGER.CPP. Click OK to save the file.

To run the program, choose Run from the Run menu. The compiler will build the program and then run it. When

Enter new value

appears on the screen, enter 88, 93.6, 89, 92.9, and 45.1 as new values. When you enter the last number, the output from the program should be similar to what appears in Figure A.


Figure A - The AVERAGER program simply calculates a running average with a single-function class.

Enter new value 88
Average is 88
Enter new value 93.6
Average is 90.800003
Enter new value 89
Average is 90.200005
Enter new value 92.9
Average is 90.875
Enter new value 45.1
Average is 81.720001

To end the program and return to the IDE, enter -1. To exit the IDE, choose Quit from the File menu.

Conclusion

The syntax of overloading the function call operator confuses many programmers when they see it for the first time. However, if you know how to apply this syntax, you can overload operator () to provide an appropriately simple interface for your own classes.

Return to the Borland C++ Developer's Journal index

Subscribe to the Borland C++ Developer's Journal


Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.