Function Overloading

C++ allows specification of more than one function of the same name in the same scope. These are called “overloaded functions” and are described in detail in Chapter 12, Overloading. Overloaded functions enable programmers to supply different semantics for a function, depending on the types and number of arguments.

For example, a print function that takes a string (or char *) argument performs very different tasks than one that takes an argument of type double. Overloading permits uniform naming and prevents programmers from having to invent names such as print_sz or print_d. Table 7.3 shows what parts of a function declaration C++ uses to differentiate between groups of functions with the same name in the same scope.

Table 7.3   Overloading Considerations

Function Declaration Element Used for Overloading?
Function return type No
Number of arguments Yes
Type of arguments Yes
Presence or absence of ellipsis Yes
Use of typedef names No
Unspecified array bounds No
const or volatile (in cv-mod-list) Yes

Although functions can be distinguished on the basis of return type, they cannot be overloaded on this basis.

The following example illustrates how overloading can be used. Another way to solve the same problem is presented in Default Arguments.

#include <iostream.h>
#include <math.h>
#include <stdlib.h>

// Prototype three print functions.
int print( char *s );                  // Print a string.
int print( double dvalue );            // Print a double.
int print( double dvalue, int prec );  // Print a double with a
                                       //  given precision.
void main( int argc, char *argv[] )
{
    const double d = 893094.2987;

    if( argc < 2 )
    {
        // These calls to print invoke print( char *s ).
        print( "This program requires one argument." );
        print( "The argument specifies the number of" );
        print( "digits precision for the second number" );
        print( "printed." );
    }

    // Invoke print( double dvalue ).
    print( d );

    // Invoke print( double dvalue, int prec ).
    print( d, atoi( argv[1] ) );
}

// Print a string.
int print( char *s )
{
    cout << s << endl;
    return cout.good();
}

// Print a double in default precision.
int print( double dvalue )
{
    cout << dvalue << endl;
    return cout.good();
}

// Print a double in specified precision.
//  Positive numbers for precision indicate how many digits'
//  precision after the decimal point to show. Negative
//  numbers for precision indicate where to round the number
//  to the left of the decimal point.
int print( double dvalue, int prec )
{
    // Use table-lookup for rounding/truncation.
    static const double rgPow10[] = { 
        10E-7, 10E-6, 10E-5, 10E-4, 10E-3, 10E-2, 10E-1, 10E0,
        10E1,  10E2,  10E3,  10E4, 10E5,  10E6
    };
    const int iPowZero = 6;

    // If precision out of range, just print the number.
    if( prec < -6 || prec > 7 )
        return print( dvalue );

    // Scale, truncate, then rescale.
    dvalue = floor( dvalue / rgPow10[iPowZero - prec] ) *
                             rgPow10[iPowZero - prec];

    cout << dvalue << endl;
    return cout.good();
}

The preceding code shows overloading of the print function in file scope.

For restrictions on overloading and information on how overloading affects other elements of C++, see Chapter 12, Overloading.