See how we can create different versions of functions by using different parameter types
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

###### Ryan McCombe
Posted

We have been using a TakeDamage function quite a lot in previous examples. It is a simple function that allows our Characters to take an integer amount of damage:

// Take 30 Damage
Character.TakeDamage(30);


However, it might be useful to have another version of that function. Instead of taking an integer amount of damage, that function could let our characters take a percentage of their health as damage.

We could call that version by passing a floating point number:

// Take 20% damage
Character.TakeDamage(0.2f);


### Why the f in 0.2f?

In an earlier note covering the concepts of literals, we pointed out that 0.2 is actually interpreted as a double, rather than a float. For it to be a float literal, we would need to add an f, as in 0.2f.

We agreed to leave the f off because it makes our code easier to understand for beginners, and it also would let us point out scenarios where the f matters.

The above example is one such scenario.

Imagine we have two versions of a function - one that accepts an int as a parameter, and the other that accepts a float. We call that function with a double as a parameter, such as 0.2.

We've already seen that a double can be implicitly converted to a float. The problem here is that a double can also be implicitly converted to an int.

Therefore, the compiler doesn't know what we want. Does it convert the double to an int and call the first function, or does it convert the double to a float and call the second? Rather than guess, it asks us to clarify our intentions.

We can help it out by adding the f to our literal - 0.2f. Then, we are passing a float rather than a double, and the compiler can be certain we want to call the version of the function that uses a float.

The upcoming lesson on Static Casting will introduce how we can take full control over this process, rather than always relying on implicit conversions.

This approach of having multiple functions with the same name is an example of static overloading. Lets see how we can set this up!

This behaviour, where we have a function with the same name, but with different parameter types, is called an overloaded function.

The way we create it is perhaps exactly like you'd expect. We simply define two functions with the same name - one that accepts an integer, and the other that accepts a float:

class Character {
public:
void TakeDamage(int Damage) {
Health -= Damage;
};
void TakeDamage(float Percent) {
Health *= (1-Percent);
};
private:
int Health { 150 };
}


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

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

bool MyBool { GetBool(5) };


## Improving the Design with Wrapping Functions

In the real world, our TakeDamage functions are likely to be a lot more complicated than the simple example above. For example:

class Character {
public:
void TakeDamage(int Damage) {
Health -= Damage;
PlayAnimation();
RenderEffects();
PlaySound();
UpdateAI();
UpdateHealthBar();
};
void TakeDamage(float Percent) {
Health *= (1-Percent);
PlayAnimation();
RenderEffects();
PlaySound();
UpdateAI();
UpdateHealthBar();
};
private:
int Health { 150 };
}


These functions are now duplicating code, and will be difficult to maintain in the future.

A common pattern to deal with this is to have only one function be our primary version, where all the heavy work is done.

The overloaded versions can just be simple wrappers that convert arguments to the appropriate values, then defer to the primary version of the function. That might look something like this:

class Character {
public:
void TakeDamage(int Damage) {
Health -= Damage;
PlayAnimation();
RenderEffects();
PlaySound();
UpdateAI();
UpdateHealthBar();
};
void TakeDamage(float Percent) {
int Damage { Health * Percent };
TakeDamage(DamageToInflict)
};
private:
int Health { 150 };
}


Now, we have the primary TakeDamage function, where most of our effort can be focused. The float version of our function is just a simple wrapper around it.

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

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

bool MyBool { GetBool(5.0) };


The next lesson will introduce Static Casting.

Casting is how we can take full control of the data conversion process. It lets us explicitly issue instructions to convert our data into different types. This means we're taking full control of the process, and not always relying on implicit conversion as we have been thus far.

###### Ryan McCombe
Posted
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

###### 27.

See how we can create different versions of functions by using different parameter types

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:

• 66 Lessons
• Over 200 Quiz Questions
• Capstone Project
• Regularly Updated
• Help and FAQ
Next Lesson

### Static Casting in C++ with static_cast

Take control of our data types, and convert between them explicitly using static casting.