Advanced OOP using C++

Function Overloading

Published:  August 5, 2008
By Richard G. Baldwin

File:  AdvCpp00130


Preface

General

The purpose of this series of tutorial lessons is to help you progress from procedural programming using C++ to object-oriented programming (OOP) using C++.  As I have mentioned in earlier lessons (see Resources), the code in this lesson will be written in such a way as to make it compatible with the display of output data on the command-line screen using Dev-C++.  However, you can easily modify the code to make it compatible with other C++ programming tools.

Viewing tip

I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.

Figures

Listings

Supplementary material

I recommend that you also study the other lessons in my extensive collection of online programming tutorials.  You will find a consolidated index at www.DickBaldwin.com.

General background information

Function overloading is the C++ technique that allows you to give more than one function the same name in the same scope.  (Other OOP languages such as Java and C# also support function overloading.)

In C, each function having a specific name is restricted to operating on data of a specified type or a specific combination of types. In C++, two or more functions having the same name (but different formal argument lists) can exist in the same scope and can be written in such a way that they will be selected for execution on the basis of the type and/or the number of arguments in the formal argument list.

The classic example

The classic example that appears in many textbooks is that in C, different functions with different names are necessary to determine the absolute value of a numeric value when that value is represented as different types.  This is the case because in C, only one function with a given name is allowed to exist in the same scope, regardless of the formal argument list ascribed to the function name.

More correct terminology
It is probably more correct to refer to the function name as being overloaded than to refer to the function itself as being overloaded. However, common jargon usually refers to the function as being overloaded.

The C++ solution

In C++, two or more functions can be written with the same name in the same scope, each of which can handle a different type of data. These are commonly referred to as overloaded functions.

Ambiguous functions
It is possible to write overloaded functions in such a way that they are ambiguous, thus preventing the compiler from being able to make a selection.  This will result in an error at compile time.

Therefore, two or more different functions with the same name can be written, each of which will return the absolute value of a different type of data.  When the program is compiled, the compiler will choose among the set of overloaded functions having the same name, choosing the most appropriate function on the basis of the parameters that are passed to the function.

Compile-time polymorphism

This is one of the programming techniques used to achieve polymorphism. This particular kind of polymorphism is often referred to as compile-time polymorphism because the selection among different functions having the same name is made when the program is compiled.  A discussion of runtime polymorphism is provided in a subsequent lesson. Polymorphism is often described as "one interface, multiple methods."

Preview

You will learn that in C++, two or more functions can share the same name in the same scope as long as either the type of their arguments differs, or the number of their arguments differs, or both.

You will learn that return type alone is not a sufficient difference to cause two functions to be overloaded. If two functions differ only in the type of data they return, the compiler will not be able to select the proper one to call.

You will learn that function overloading is one of the aspects of C++ that supports the OOP programming paradigm. However, you will also learn that you can also use function overloading in your traditional non-OOP C++ programs to design and develop improved programs as well.

Discussion and sample code

In C, you cannot use the same function name more than once in the same scope. However, in C++ you can use a function name more than once in the same scope if the number of parameters, the type of parameters, or both, are different. Multiple functions having the same name are then available at the same time. This feature is called function overloading. With function overloading, you can define multiple versions of functions having the same name but having differences in their formal parameter lists.

Compile-time polymorphism

Function overloading provides the mechanism by which C++ achieves a kind of polymorphism often referred to as compile-time polymorphism.

Operator overloading

It forms the basis by which the C++ programming environment can be extended by supporting operator overloading, which will be explained in a future lesson.

Overloaded constructors

Finally, it provides the mechanism by which different objects can be instantiated from the same class by passing different numbers of parameters, different types of parameters, or both to the constructor for the class.

Reduced complexity

Overloaded functions help reduce the complexity of a program by allowing related operations to be referred to by the same name.

It is easy to overload a function. Simply declare and define all required versions. The compiler will automatically select the correct version to call based upon the number and/or the type of the arguments used to call the function.

Overloading for different operations

An example of C functions that provide a good candidate for overloading is the set of C functions that return the absolute value. There are at least three such functions in C: abs, labs, and fabs. These three functions accept incoming parameter values of type int, long, and double respectively and return the absolute value of the parameter in each case.

Source code for the program named Prog130A

The C++ program in Listing 1 defines three overloaded functions, all named xAbs, and all in the same scope, which return the absolute value of parameter values of types int, long, and double.

Listing 1. Source code for the program named Prog130A.
//File Prog130A
/*********************************************************
Overloaded Functions
This program provides an example of three overloaded
functions, all named xAbs, and all in the same scope,
which return the absolute values of data values of types
int, long, and double.
*********************************************************/

#include 
using namespace std;

// Overload xAbs() in three ways
int xAbs(int);
long xAbs(long);
double xAbs(double);

int main(){
  cout << "Abs value of -10: " << xAbs(-10) << "\n";
  cout << "Abs value of -10L: " << xAbs(-10L) << "\n";
  cout << "Abs value of -10.01: " << xAbs(-10.01) << "\n";

  //return 0;
  //Following statements cause Dev-C++ output to remain
  // on the screen
  system("PAUSE");
  return EXIT_SUCCESS;
}// end main

// xAbs() for ints
int xAbs(int n){
  cout << "In integer xAbs()\n";
  return n < 0 ? -n : n;
}//end xAbs() for ints

// xAbs() for longs
long xAbs(long n){
  cout << "In long xAbs()\n";
  return n < 0 ? -n : n;
}//end xAbs() for longs

// xAbs() for doubles
double xAbs(double n){
  cout <<"In double xAbs()\n";
  return n<0 ? -n : n;
}//end xAbs() for doubles

Return types for overloaded functions
The return types for overloaded functions may be the same or may be different.

Three functions in the same scope

This program defines three functions, all named xAbs, and all in the same scope.  Each function is defined to process a different type of data: int, long, and double.  Formal parameters of different types appear in the function prototypes for each of the three functions and this differentiates among the three functions insofar as the C++ compiler is concerned.

Demonstrating the use of the overloaded functions

The code in the main function demonstrates the use of the overloaded functions.  The main function calls xAbs three times in succession passing a different type of parameter with each call.  The main function also displays the return values from each call along with some explanatory text.  The screen output is shown in Figure 1.

Figure 1. Screen output from the program named Prog130A.
In integer xAbs()
Abs value of -10: 10
In long xAbs()
Abs value of -10L: 10
In double xAbs()
Abs value of -10.01: 10.01
Press any key to continue . . .

Constructor overloading
While one might argue that this form of function overloading is for convenience only, you will learn later that constructors can also be overloaded, providing capabilities that would not be possible without overloading.

A general class of action with a single name

This simple example illustrates the value of function overloading. Because one name is used to describe a general class of action, the artificial complexity caused by three slightly different names, abs, fabs, and labs has been eliminated. Now you only have to remember the one name that describes the general action. It is left to the compiler to choose the specific version of the function to execute. This has the net effect of reducing complexity. Three names have been reduced to one. This is an example of "compile-time" polymorphism. "Run-time" polymorphism will be discussed later in future lessons.

Overloading for different formats

Another reason to overload a function is to get the same result from data values that can be represented in different formats.

The function named date in Listing 2 is overloaded to accept the date either as a string or as three integers. In both cases, the function displays the date passed to it.

Listing 2. Source code for the program named Prog130B.
//File Prog130B
/*********************************************************
Overloaded Functions
The function date is overloaded to accept the date either
as a string or as three integers.  In both cases, the
function displays the date passed to it.

*********************************************************/

#include 
using namespace std;

// Overload date() in two ways
void date(char*);//date as a string,mo/day/year
void date(int,int,int);//date as ints day,month,year

int main(){
  date("8/3/2008");
  date(8,3,2008);
  
  //return 0;
  //Following statements cause Dev-C++ output to remain
  // on the screen
  system("PAUSE");
  return EXIT_SUCCESS;
}// end main

//Process date as a string
void date(char *date){
  cout << "In date as a string function\n";
  cout << "Date: " << date << "\n";
}//end date as a string

//Date as integers
void date(int month, int day, int year){
  cout << "In date as integers function\n";
  cout << "Date: " << month << "/" << day << "/"
                                          << year << "\n";
}//end date as integers

A more natural programmer interface

This example illustrates how function overloading can provide the most natural interface to a function. Since it is very common for the date to be represented either as a string or as three integers containing the month, day, and year, the programmer is free to select the most convenient version relative to the situation at hand.

The screen output produced by executing the program in Dev-C++ is shown in Figure 2.

Figure 2. Screen output from the program named Prog130B.
In date as a string function
Date: 8/3/2008
In date as integers function
Date: 8/3/2008
Press any key to continue . . .

Overloading by number of arguments

So far, you have seen overloaded functions that differ in the data types of their arguments. However, overloaded functions can also differ in the number of arguments with no difference in the types of arguments as the example program in Listing 3 illustrates.

Listing 3. Source code for the program named Prog130C
//File Prog130B
/*********************************************************
Overloaded Functions
This program overloads a function named fun with different
numbers of arguments.
*********************************************************/

#include 
using namespace std;

// Overload fun in two ways
void fun(int);
void fun(int,int);

int main(){
  fun(10);
  fun(10, 20);
  
  //return 0;
  //Following statements cause Dev-C++ output to remain
  // on the screen
  system("PAUSE");
  return EXIT_SUCCESS;
}// end main

void fun(int a){
  cout << "In function with one argument\n";
  cout << "The argument is: " << a << "\n";
}//end fun with one argument

void fun(int a, int b){
  cout << "In function with two arguments\n";
  cout << "The arguments are: " << a << " and " << b
                                                  << "\n";
}//end function with two arguments

In this example, all of the arguments are of type int. The compiler can distinguish between the different functions on the basis of the number of arguments.

The screen output from this program is shown in Figure 3.

Figure 3. Screen output from the program named Prog130C.
In function with one argument
The argument is: 10
In function with two arguments
The arguments are: 10 and 20
Press any key to continue . . .

Summary

In C++, two or more functions can share the same name in the same scope as long as either the type of their arguments differs, or the number of their arguments differs, or both.

Return type alone is not a sufficient difference to cause two functions to be overloaded. If two functions differ only in the type of data they return, the compiler will not be able to select the proper one to call.

Function overloading is one of the aspects of C++ that supports the OOP programming paradigm. However, as the examples in this lesson show, you can also use function overloading in your traditional non-OOP C++ programs to design and develop improved programs as well.

Complete program listings

Complete listings of the programs discussed in this lesson are all embedded in the text of the discussions.

Resources


Copyright

Copyright 2008, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java, C#, and XML. In addition to the many platform and/or language independent benefits of Java and C# applications, he believes that a combination of Java, C#, and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Programming Tutorials, which have gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.

In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP).  His first job after he earned his Bachelor's degree was doing DSP in the Seismic Research Department of Texas Instruments.  (TI is still a world leader in DSP.)  In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

Baldwin@DickBaldwin.com

-end-