Function Overloading

This lesson provides an in-depth look at function overloading in C++, covering its importance, implementation, and best practices
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, Unlimited Access
3D art showing a character using a compass
Ryan McCombe
Ryan McCombe
Updated

Polymorphism is a principle in programming where the same expression can have multiple forms, based on the context in which it is used, or the data types it is used with.

This approach can keep our code simple and readable, even as our program gets more and more complex. In C++, polymorphism manifests mainly in three forms:

1. Overloading

This includes both operator and function overloading.

  • Operator Overloading: Previously, we discussed how operator overloading allows operators to have different behaviors based on their arguments. For example, expressions like A + B will do different things based on the types of A and B.
  • Function Overloading: Function overloading allows multiple functions to have the same name but different parameter lists (either in the number of parameters or their type). This enables an expression like CalculateArea(MyObject) to behave differently based on the type of MyObject.

2. Templates

Templates allow us to define recipes for blocks of code. The compiler can then use these recipes to generate functions or entire classes that adapt to our needs.

We cover templates in more detail in the next course.

3. Run Time Polymorphism

Run Time Polymorphism, which we will delve into later in this chapter, interacts with the inheritance trees, pointers, and references we introduced earlier. It allows our code to behave much more dynamically, without introducing excessive complexity.

Overloading Functions

To overload functions, we simply define functions within the same scope, that have the same name, but have a different parameter list.

Below, we define a Rectangle and Circle type. Alongside each class, we provide standalone CalculateArea() functions:

struct Rectangle {
  float Width;
  float Height;
};

float CalculateArea(const Rectangle& R){
  return R.Width * R.Height;
}
struct Circle {
  float Radius;
};

float CalculateArea(const Circle& C){
  return 3.14 * C.Radius * C.Radius;
}

When these functions are both available, they’re considered overloaded.

Elsewhere, in code that uses our classes, we can use a consistent syntax. We can just pass an object to CalculateArea(SomeObject), and that expression adapts based on the type of SomeObject.

From the perspective of the consumer, it doesn’t look like they’re calling two different functions, rather it seems like they’re calling a single, polymorphic function:

int main(){
  Circle MyCircle{2};
  cout << "Circle Area: "
    << CalculateArea(MyCircle);

  Rectangle MyRectangle{3, 4};
  cout << "\nRectangle Area: "
    << CalculateArea(MyRectangle);
}
Circle Area: 12.56
Rectangle Area: 12
Test your Knowledge

Function Overloading

After running the following code, what is the value of MyBool?

bool IsFloat(float Number) { return true; }
bool IsFloat(int Number) { return false; }

bool MyBool { IsFloat(5) };

Overloading Member Functions

Member functions can also be overloaded in the same way. Let's imagine we have the following situation, where our Character objects can equip weapons:

class Weapon{};

class Character {
 public:
  void Equip(Weapon* Weapon){
    mWeapon = Weapon;
  }

 private:
  Weapon* mWeapon{nullptr};
};

int main(){
  Character Player;
  Weapon WoodenSword;
  Player.Equip(&WoodenSword);
}

We’d like to be able to equip other items too. Our first instinct to accommodate this might be to rename our existing Equip() function to EquipWeapon(), and then add new functions called EquipArmor(), EquipShield(), and so on.

But we don’t need to - we can just overload the Equip() function, keeping our class friendly to use:

class Weapon {};

class Shield {};

class Character {
public:
  void Equip(Weapon* Weapon){
    mWeapon = Weapon;
  }

  void Equip(Shield* Shield){
    mShield = Shield;
  }

private:
  Weapon* mWeapon{nullptr};
  Shield* mShield{nullptr};
};

int main(){
  Character Player;
  Weapon WoodenSword;
  Player.Equip(&WoodenSword);

  Shield WoodenShield;
  Player.Equip(&WoodenShield);
}

Ambiguous Function Calls

When we’re working with overloaded functions, we may see the compiler report errors, claiming our function calls are ambiguous.

In these scenarios, we often need to be more explicit about our data types.

An example of a simple program that falls foul of this rule is below:

void Func(int Arg){}
void Func(float Arg){}

int main(){
  Func(1.5);
}
'Func': ambiguous call to overloaded function

In an earlier note covering the concepts of literals, we pointed out that a literal like 1.5 is interpreted as a double, rather than a float. Float literals append an f, as in 1.5f.

So far, we have omitted the f to make our code easier to read for beginners, and because it generally doesn’t matter - doubles can be implicitly converted to floats.

However, doubles can be implicitly converted to integers, too, which causes a problem in this context.

Without the f, our code is ambiguous. Should the compiler convert the double to an int and call Func(int)? Or should it convert it to a float and call Func(float)?

Rather than guessing our intentions, it asks us to clarify.

In the next lesson, we’ll see how we can solve problems like this by being explicit about our conversions. For now, we can do it manually:

void Func(int Arg){}
void Func(float Arg){}

int main(){
  // Call Func(int)
  Func(1);

  // Call Func(float)
  Func(1.5f);
}
Test your Knowledge

Function Overloading

After running the following code, what is the value of MyBool?

bool IsDouble(double Number) { return true; }
bool IsDouble(float Number) { return false; }

bool MyBool { IsDouble(5) };

Summary

In this lesson, we delved into several key concepts:

  • Understanding Polymorphism and Overloading: We started by exploring polymorphism and explaining the main ways we can implement it in C++.
  • Function Overloading with Different Types: We learned how to overload functions by creating functions with the same name but different parameters
  • Overloading Member Functions: The concept was further extended to member functions in classes, illustrating a Character class that can equip different items like weapons and shields.
  • Resolving Ambiguities in Overloaded Functions: We addressed potential ambiguities that arise with overloaded functions and how to resolve them

Preview: Casting

In our upcoming lesson on casting, we will explore type conversion in more depth. Here's what you can expect:

  • Introduction to Casting: We'll start by defining what casting is
  • Static Casting: We'll explore the different types of casting available in C++, specifically focusing on static casting.
  • C-Style Casting: We will introduce an older casting syntax, sometimes referred to as C-style casting.
  • Best Practices and Pitfalls: Finally, we will cover some shortcomings of C-style casting, explaining why we should prefer alternative approaches

Was this lesson useful?

Next Lesson

Static Casting

Explore the concept of static casting in C++, including examples and best practices for converting data types at compile time
3D art showing a fantasy character working in an office
Ryan McCombe
Ryan McCombe
Updated
Lesson Contents

Function Overloading

This lesson provides an in-depth look at function overloading in C++, covering its importance, implementation, and best practices

3D art showing a progammer setting up a development environment
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, Unlimited Access
Polymorphism
3D art showing a progammer setting up a development environment
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, unlimited access

This course includes:

  • 56 Lessons
  • Over 200 Quiz Questions
  • 95% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Next Lesson

Static Casting

Explore the concept of static casting in C++, including examples and best practices for converting data types at compile time
3D art showing a fantasy character working in an office
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved