Overloading and Default Arguments

C++ lets several functions share one name as long as their parameters differ — overloading — and lets parameters have default values. Both make functions easier to call without inventing names like print_int and print_double.

Function overloading

C++
#include <iostream>
#include <string>
#include <vector>

void show(int value)                  { std::cout << "int: " << value << '\n'; }
void show(double value)               { std::cout << "double: " << value << '\n'; }
void show(const std::string& value)   { std::cout << "string: \"" << value << "\"\n"; }
void show(const std::vector<int>& v)  { std::cout << "vector of " << v.size() << " ints\n"; }

int main() {
    show(42);
    show(3.5);
    show(std::string{"hello"});
    show(std::vector<int>{1, 2, 3});
}
Output
int: 42
double: 3.5
string: "hello"
vector of 3 ints

The compiler picks the overload whose parameters best match the arguments. Overloads must differ in their parameter types or count — a different return type alone isn't enough.

Ambiguity

When two overloads match equally well, the call is ambiguous and won't compile:

C++
void scale(float factor) {}
void scale(long factor) {}

int main() {
    scale(2);      // int converts equally well to float or long
}
Compiler error
main.cpp:5:5: error: call to 'scale' is ambiguous

Fix it by passing an argument of the exact type (2L, 2.0f) or by adding an int overload. Keep overload sets small and obviously related.

Default arguments

Parameters can have default values, used when the caller leaves them out. Defaults must come at the end of the parameter list:

C++
#include <iostream>
#include <string>

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

int main() {
    greet("Ada");
    greet("Grace", "Welcome");
    greet("Linus", "Hi", 2);
}
Output
Hello, Ada!
Welcome, Grace!
Hi, Linus!
Hi, Linus!

Put the default in the declaration (usually in a header) only — not repeated in the definition.

Overloading vs. defaults vs. templates

  • Default arguments — when the function does the same thing and some inputs usually have the same value.
  • Overloads — when different input types need genuinely different code.
  • Templates (lesson 39) — when the same code works for many types.
C++
#include <iostream>

template <typename T>
T largest(T a, T b) {
    return a > b ? a : b;
}

int main() {
    std::cout << largest(3, 9) << ' ' << largest(2.5, 1.5) << ' ' << largest('a', 'z') << '\n';
}
Output
9 2.5 z

inline functions

Short functions defined in headers are often marked inline. In modern C++ this doesn't mainly mean "insert the code at the call site" (the optimiser decides that on its own); it means the definition may appear in several source files without breaking the one-definition rule (lesson 48).

Try it yourself

Write circle_area for a circle, then two overloads of area: one for a rectangle (width, height) and one taking a single int for a square.

Try it yourself · main.cpp
Edit the code, copy it into main.cpp, then compile and run it with c++ -std=c++20 -Wall main.cpp -o main && ./main. How to set up a C++ compiler
Output
circle r=2: 12.5664
rect 3x4:   12
square 5:   25