This page was last updated August, 2004


Function Overloading and Polymorphism


Function Overloading is the ability of two functions with the same name but different parameters and functionality to exist in the same program.

Suppose you have a situation in a program where you need fucntions to multiply two numbers together. But, sometimes those two numbers are ints, sometimes they are longs, sometimes floats, and sometimes doubles. You could create four different functions:


int Multiply2Ints(int arg1, int arg2);
long Multiply2Longs(long arg1, long arg2);
float Multiply2Floats(float arg1, float arg2);
double Multiply2Doubles(double arg1, double arg2);

If, however, we use polymorphism we can define four functions with the same name like this:


int Multiply(int arg1, int arg2);
long Multiply(long arg1, long arg2);
float Multiply(float arg1, float arg2);
double Multiply(double arg1, double arg2);

The compiler is able to determine which of these functions to call based on the type of arguments. It is even able to call the correct function when the number of arguments is different as in the following


int Multiply (int arg1, int arg2, int arg3);
long Multiply (long arg1, long arg2, long arg3);
float Multiply (float arg1, float arg2, float arg3);
double Multiply (double arg1, double arg2, double arg3);

In fact all the arguments do not even have to be the same type as in the following:


long Multiply (int arg1, long arg2);
double Multiply (float arg1, double arg2);

Below is an example of a short program demonstrating this:
//=======================================================
// File: main.cpp
// Purpose: Demonstrate function overloading
// Author: Dr. Rick Coleman
//=======================================================
#include <iostream.h>

// Function prototypes
int Multiply (int arg1, int arg2);
long Multiply (long arg1, long arg2);
float Multiply (float arg1, float arg2);
double Multiply (double arg1, double arg2);
int Multiply (int arg1, int arg2, int arg3);
long Multiply (long arg1, long arg2, long arg3);
float Multiply (float arg1, float arg2, float arg3);
double Multiply (double arg1, double arg2, double arg3);
long Multiply (int arg1, long arg2);
double Multiply (float arg1, double arg2);



int main()
{
	int a = 1, b = 2, c = 3;
	long d = 4, e = 5, f = 6;
	float g = 7.0f, h = 8.0f, i = 9.0f;
	double j = 10.0, k = 11.0, l = 12.0;

	cout << "Multiply(int, int) = " << Multiply(a, b) << "\n";
	cout << "Multiply(long, long) = " << Multiply(d, e) << "\n";
	cout << "Multiply(float, float) = " << Multiply(g, h) << "\n";
	cout << "Multiply(double, double) = " << Multiply(j, k) << "\n";

	cout << "Multiply(int, int, int) = " << Multiply(a, b, c) << "\n";
	cout << "Multiply(long, long, long) = " << Multiply(d, e, f) << "\n";
	cout << "Multiply(float, float, float) = " << Multiply(g, h, i) << "\n";
	cout << "Multiply(double, double, double) = " << Multiply(j, k, l) << "\n";

	cout << "Multiply(int, long) = " << Multiply(a, d) << "\n";
	cout << "Multiply(float, double) = " << Multiply(g, j) << "\n";

	return 0;
}

// Multiply two ints
int Multiply (int arg1, int arg2)     
{
	return arg1 * arg2;
}

// Multiply two longs
long Multiply (long arg1, long arg2)
{
	return arg1 * arg2;
}

// Multiply two floats
float Multiply (float arg1, float arg2)
{
	return arg1 * arg2;
}

// Multiply two doubles
double Multiply (double arg1, double arg2)
{
	return arg1 * arg2;
}

// Multiply three ints
int Multiply (int arg1, int arg2, int arg3)
{
	return arg1 * arg2 * arg3;
}

// Multiply three longs
long Multiply (long arg1, long arg2, long arg3)
{
	return arg1 * arg2 * arg3;
}

// Multiply three floats
float Multiply (float arg1, float arg2, float arg3)
{
	return arg1 * arg2 * arg3;
}

// Multiply three doubles
double Multiply (double arg1, double arg2, double arg3)
{
	return arg1 * arg2 * arg3;
}

// Multiply an int and a long
long Multiply (int arg1, long arg2)
{
	return arg1 * arg2;
}

// Multiply a float and a double
double Multiply (float arg1, double arg2)
{
	return arg1 * arg2;
}

Polymorphism is the ability of different sub-classes of a parent class to inherit functions from the parent class yet implement the functions in very different ways. In a way this is function overloading by changing the function’s operation.

A classical example of this is in a drawing application. Suppose you wanted to create a drawing package in which the user could select from a tool bar a rectangle, oval, etc. shape and then draw that shape using mouse click-and-drag operations. This could be implemented by creating a rectangle class, an oval class, and a class for each of the shapes you want to draw. Since all these shapes would share many common characteristics, such as line color, fill color, line pattern, fill pattern, a bounding rectangle, etc. it makes sense to create a shape class and then create sub-classes of this class. Below is the header file for an application which defines a CShape class. Note: If this were an actual program we would have all the common variables like line color defined in this file and let them be inherited by the sub-classes.

//============================================================
// File: CShape.h
// Purpose: Define the base class for a shape hierarchy
// Author: Dr. Rick Coleman
//============================================================
#ifndef CSHAPE_H
#define CSHAPE_H

class CShape
{
	public:
		CShape();
		~CShape();
		virtual void draw();
};

#endif
Notice how the draw() function is defined in CShape.h. It is declared as virtual. This means that all subclasses will be required to implement this function instead of inheriting it from the parent class. We can now proceed to define a CRectangle class and a COval class as shown below.

//============================================================
// File: CRect.h
// Purpose: Define the derived rectangle class
// Author: Dr. Rick Coleman
//============================================================
#ifndef CRECT_H
#define CRECT_H

#include "CShape.h"

class CRect:CShape
{
	public:
		CRect();
		~CRect();
		void draw();
};
#endif
//============================================================
// File: COval.h
// Purpose: Define the derived oval class
// Author: Dr. Rick Coleman
//============================================================
#ifndef COVAL_H
#define COVAL_H

#include "CShape.h"

class COval:CShape
{
	public:
		COval();
		~COval();
		void draw();
};
#endif
Note that in CRect.h and COval.h the draw function is not declared as virtual. In each case the code in the class would be written to draw the appropriate shape.
With these classes we could now create some simple program using the classes such as the one below.

//============================================================
// File: ShapeDemo.cpp
// Purpose: Demonstrate the use of polymorphism.
// Author: Dr. Rick Coleman
//============================================================
#include "CShape.h"
#include "CRect.h"
#include "COval.h"

int main(void)
{
   CShape    *theRect, *theOval;     // Declare pointers to two CShape objects

   theRect = new(CRect);	// Instantiate this CShape as a CRect object
   theOval = new(COval);	// Instantiate this CShape as a COval object

   // Call appropriate functions to set drawing colors, sizes etc. for each

   // Call the functions in the each sub-class to tell the objects to draw themselves
   theRect->Draw();
   theOval->Draw();

   // Do some other stuff here

   // Destroy the objects when finished
   delete theRect;
   delete theOval;
}