Unit 12: Function overloading

  1. Function overloading
  2. Unique signatures
  3. Member functions
  4. Overloading constructors
  5. Shallow copy vs. deep copy

  6. Example code and additional resources

This week's stuff:

Function overloading

In C++ you can write multiple functions with the same name, as long as it has a different parameter list so the compiler can tell the two functions apart. Doing this is called function overloading.

int Sum( int a, int b )
{
    return a + b;
}

float Sum( float a, float b )
{
    return a + b;
}
        

Function overloading can be useful for scenarios where we might have different amounts of information to pass into the function at different times, or different versions of a function that handle different data types. For example:

  • Setup function, given parameters A, B, C... - Maybe some info is available "here" but not "there".
  • Display function, given different object types - Perhaps a "rectangle" is drawn differently from a "circle".

Unique signatures

You can write as many functions with shared names as you'd like, as long as each function has different parameters. This means:

  • The functions have different amounts of parameters, or
  • The data types of the parameters are different, or
  • The parameters are in a different order (when mixing data types).

Parameter variable names don't affect the "uniqueness" of a function signature, it has to be different data types, different order, or different amounts of parameters.

void Setup( string log_file );
void Setup( string log_file, bool is_debug );

void Draw( Rectangle rect );
void Draw( Circle circle );

Member functions

We can also overload member functions (aka methods) within a class. The same rules apply, just now the functions belong to a class.

// CLASS/FUNCTION DECLARATION
class Program
{
	public:
	void Setup( string log_file );
	void Setup( string log_file, bool is_debug );
};

// FUNCTION DEFINITIONS
void Program::Setup( string log_file )
{
	// ...
}

void Program::Setup( string log_file, bool is_debug )
{
	// ...
}

// WITHIN MAIN/OTHER FUNCTIONS:
Program prog;
prog.Setup( "Log.txt" );

Program debug_prog;
debug_prog.Setup( "DebugLog.txt", true );

Overloading constructors

A really handy use of overloading functions is to overload a class' constructors. There are three main types of constructors we may want for any given class:

  1. A Default Constructor, where member variables are given default values.
    File() {
    	this->filename = "default.txt";
    }
  2. A Parameterized Constructor, where initial data is provided to the class.
    File( string name ) {
    	this->filename = name;
    }
  3. A Copy Constructor, where another object of this type is passed in, and we copy the data from that other object to this object.
    File( const File& other ) {
    	this->filename = other.filename;
    }

Shallow copy vs. deep copy

When writing a copy constructor you will need to decide what kind of copy will occur...

A Shallow Copy is where values of variables are copied over.

This is usually fine for classes that don't work with pointers. However, if the class has a pointer as a member variable, keep in mind that the original and the copy will both point to the same memory address.

If you're not expecting this, this can create memory management errors down the road.
A Deep Copy is where new memory is allocated for any of the pointer member variables. The original and the copy will point to different memory addresses, but you can copy the value so that both memory addresses have the same value.

This is usually safer, and usually more in-line with what someone would expect from a copy by default.

Example code and additional resources

Spring 2024 lecture:

  • WORK IN PROGRESS