CodeMIRAI
0 XP

Function overloading

2 min read 3 runnable examples Quiz included

In C, every function needs its own name: area_square, area_rect, area_circle. C++ lets them share one name, as long as their parameter lists differ. This is function overloading.

Same name, different parameters

C++
#include <iostream>
using namespace std;

int area(int side) { return side * side; }
int area(int width, int height) { return width * height; }
double area(double radius) { return 3.14159 * radius * radius; }

int main() {
    cout << area(4) << endl;        // one int: a square
    cout << area(3, 5) << endl;     // two ints: a rectangle
    cout << area(2.0) << endl;      // one double: a circle
    return 0;
}
Output
16
15
12.5664

The compiler looks at the arguments of each call and picks the version whose parameters match. It decides while compiling, so overloading costs nothing when the program runs.

Overloads may differ in the number of parameters, their types, or both.

Matching by type

C++
#include <iostream>
#include <string>
using namespace std;

void show(int n)           { cout << "int: " << n << endl; }
void show(double d)        { cout << "double: " << d << endl; }
void show(char c)          { cout << "char: " << c << endl; }
void show(const string& s) { cout << "string: " << s << endl; }

int main() {
    show(42);
    show(3.5);
    show('x');
    show(string("hello"));
    show("a literal");      // converted to string: the only version that fits
    return 0;
}
Output
int: 42
double: 3.5
char: x
string: hello
string: a literal

An exact type match wins. When there isn't one, the compiler tries standard conversions, then conversions a class provides, such as turning "a literal" into a string.

Default arguments

C++
#include <iostream>
#include <string>
using namespace std;

void greet(const string& name, const string& greeting = "Hello", int times = 1) {
    for (int i = 0; i < times; i++)
        cout << greeting << ", " << name << "!" << endl;
}

int main() {
    greet("Asha");
    greet("Leo", "Welcome");
    greet("Mei", "Hi", 2);
    return 0;
}
Output
Hello, Asha!
Welcome, Leo!
Hi, Mei!
Hi, Mei!

When versions differ only by leaving trailing arguments off, one function with default arguments is simpler than three overloads. Defaults go at the end of the parameter list, and a call can only leave arguments off from the right.

Calls the compiler can't decide

C++
void f(long x)   { }
void f(double x) { }

f(5);     // error: call of overloaded 'f(int)' is ambiguous

5 is an int. Turning it into a long and turning it into a double are equally good conversions, so neither version wins and the call doesn't compile. The fix is to say what you mean (f(5L) or f(5.0)), or to add an int overload.

The return type doesn't count

C++
int    parse(const string& s);
double parse(const string& s);    // error: only the return type differs

The compiler chooses an overload from the call's arguments, and a call like parse("3") looks the same for both. Overloads need different parameters; when you need different results, give the functions different names.

Overloading in the standard library

You've used overloads since your first program. cout << 42, cout << 3.5 and cout << "text" each call a different version of <<. Writing your own << for your own types is a later step, after classes.

Finished this lesson?Mark it complete to earn +20 XP and move your progress on.