#4 Function overloading


Function overloading

Function overloading: more than one function with the same name

May have:

Not allowed:

Compiler determines from the function prototypes which instance of the function is being called.


Function overloading example

Prototypes:

int abs(int value);
double abs(double value);

Definitions:

int abs(int value)
{
    if (value < 0)
        return -1 * value;
    else
        return value;
}

double abs(double value)
{
    if (value < 0)
        return -1 * value;
    else
        return value;
}

Calling overloaded functions

int main()
{
    int iValue = -4;
    double dValue = 0.56;

    cout << abs(iValue) << endl;
    cout << abs(dValue) << endl;
    cout << abs(-123) << endl;
    cout << abs(-6.2) << endl;
}

Allowed/disallowed

This pair of prototypes would be allowed:

double abs(int value);
double abs(double value);

This pair of prototypes would not be allowed:

int abs(int value);
double abs(int value);

Automatic type conversion

Values of type int are automatically converted to double if there are no function prototypes which match the int type. For instance:

double abs(double value);

int main
{
    int iValue;

    cout << abs(iValue) << endl;
    cout << abs(5) << endl;
}

Another example

int perimeter(int sideLength);
// For computing the perimeter of a square

int perimeter(int height, int width);
// For computing the perimeter of a rectangle

int main()
{
    cout << perimeter(5) << endl;
    cout << perimeter(4, 6) << endl;
}

int perimeter(int sideLength)
{
    return 4 * sideLength;
}

int perimeter(int height, int length)
{
    return 2 * height + 2 * length;
}

Alternate version

int perimeter(int sideLength);
// For computing the perimeter of a square

int perimeter(int height, int width);
// For computing the perimeter of a rectangle

int main()
{
    cout << perimeter(5) << endl;
    cout << perimeter(4, 6) << endl;
}

int perimeter(int sideLength)
{
    return perimeter(sideLength, sideLength);
}

int perimeter(int height, int length)
{
    return 2 * height + 2 * length;
}

Lab: Display boxes

Implement the following four functions to display a box of given size and either blank or filled with a given character. Some sample outputs are shown. Hint: you'll need nested for loops.

void displayBox(int length);
// An empty square of given size.

void displayBox(int length, char fillChar);
// A square filled with the given character.

void displayBox(int width, int height);
// An empty rectangle of given size.

void displayBox(int width, int height, char fillChar);
// A rectangle filled with the given character.


displayBox(2)     displayBox(2, 'k')      displayBox(4, 2, '*')
	
----              ----                    ------
|  |              |kk|                    |****|
|  |              |kk|                    |****|
----              ----                    ------

Call-by-reference parameters

Call-by-value parameters:

Call-by-reference parameters:


Example of need for call-by-reference

void swap(int x, int y)
{
    int temp;
    temp = x;
    x = y;
    y = temp;
}

int main()
{
    int first = 5, second = 8;

    cout << first << ", " << second << endl;
    swap(first, second);
    cout << first << ", " << second << endl;
}

What will the output be?


Same thing, now using call-by-reference

void swap(int& x, int& y)
{
    int temp;
    temp = x;
    x = y;
    y = temp;
}

int main()
{
    int first = 5, second = 8;

    cout << first << ", " << second << endl;
    swap(first, second);
    cout << first << ", " << second << endl;

    // The next line would cause a compiler error.  Why?
    swap(first + 6, 42);
}

Now what will the output be?

Note that you could overload the swap function to swap values of different types (double, char, ...).


Constant call-by-reference parameter

For larger-sized data (like structs, arrays, and classes), it's more efficient to use call-by-reference, even if the function doesn't change the value within its body. You can use a constant reference parameter to indicate and insure that your function doesn't change the value.

int DoSomething(const double& bigData)
{
    int calculatedValue;

    // do some calculation involving bigData

    // The following line should generate a compiler error.  Why?
    bigdata = 12345.6789;

    return calculatedValue;
}

Lab: Call-by-reference program trace

What is the output of the following program (which is Ch. 4, Self-Test #4, in my book) ?

void figure_me_out(int& x, int y, int& z);

int main()
{
    int a = 10, b = 20, c = 30;

    figure_me_out(a, b, c);
    cout << a << " " << b << " " << c << endl;
    return 0;
}

void figure_me_out(int& x, int y, int& z)
{
    cout << x << " " << y << " " << z << endl;
    x = 1;
    y = 2;
    z = 3;
    cout << x << " " << y << " " << z << endl;
}

A function using call-by-reference to return more than one value

void feetAndInches(int totalInches, int& feet, int& inches)
{
    inches = totalInches % 12;
    feet = (totalInches - inches) / 12;
    return;
}

int main()
{
    int total, ft, in;

    cout << "Enter total number of inches: ";
    cin >> total;

    // Notice that we don't initialize ft or in !!
    feetAndInches(total, ft, in);

    cout << total << "\" = " << ft << "\', " << in << "\"" << endl;
}

Lab: Calculating change

This is programming project 3 of Ch. 4 (in my book). Write the following function and use it to write a program that calculates what coins to give for an amount of change between 1 and 99 cents. For instance, 86 cents = 3 quarters + 1 dime + 1 penny, 43 cents = 1 quarter + 1 dime + 1 nickel + 3 pennies.

void compute_coin(int coin_value, int& number, int& amount_left);
// Precondition: 0 < coin_value < 100, 0 <= amount_left < 100
// Postcondition: number is set to the maximum number of coins of
// denomination coin_value cents that can be obtained from amount_left
// cents.  amount_left has been decreased by the value of the coins.