Skip to content

Beginner · Decisions, loops and functions · topic 8 of 42 · 25 min

Overloading, default arguments and recursion

Explanation

Function overloading lets several functions share one name if their parameter lists differ; the compiler picks the best match. Default arguments fill in values the caller leaves out. A recursive function calls itself on a smaller problem and must have a base case that stops.

Overloading: one name, many versions

In C (the older language C++ grew from), every function needs a unique name, so you get abs, labs and fabs. C++ allows overloading: functions with the same name but different parameter types or counts. The compiler looks at the arguments in each call and picks the best match. This choice is called overload resolution and it happens at compile time.

cpp
#include <iostream>
#include <string>

double area(double side) { return side * side; }                 // square
double area(double length, double width) { return length * width; }  // rectangle
std::string area(const std::string& city) { return city + " district"; }

int main() {
    std::cout << area(4.0) << '\n';          // 16
    std::cout << area(4.0, 2.5) << '\n';     // 10
    std::cout << area("Pune") << '\n';       // Pune district
}
Each call matches the version whose parameters fit its arguments.
Careful: The return type alone is NOT enough to overload. int total(); and double total(); with the same parameters is a compile error, because a call like total() could not tell them apart. Also avoid overloads that make calls ambiguous, such as f(int) and f(long) called with a double: the compiler reports "call of overloaded function is ambiguous".

Default arguments

cpp
#include <iostream>

double ticket(double base, bool tatkal = false, int passengers = 1) {
    double fare = tatkal ? base + 300 : base;
    return fare * passengers;
}

int main() {
    std::cout << ticket(800) << '\n';              // 800
    std::cout << ticket(800, true) << '\n';        // 1100
    std::cout << ticket(800, true, 3) << '\n';     // 3300
}
Parameters with defaults must come last. You cannot skip a middle one: ticket(800, , 3) is not allowed.

Put the default values in the declaration (usually in the header), not again in the definition. Writing them in both places is an error.

Recursion: a function that calls itself

Some problems are naturally made of smaller copies of themselves. The factorial of 5 is 5 × factorial of 4, and so on down to 1. A recursive function solves the problem by calling itself on a smaller input. It needs two parts: a base case that answers directly and stops, and a recursive case that moves closer to the base case.

cpp
long long factorial(int n) {
    if (n <= 1) return 1;            // base case
    return n * factorial(n - 1);     // recursive case
}

int digitSum(int n) {
    if (n < 10) return n;
    return n % 10 + digitSum(n / 10);
}
// factorial(5) == 120, digitSum(4521) == 12
Each call waits for the smaller call to finish, then finishes itself.
Think of it like this: Recursion is like a line of people passing a question back: "How many people are behind you?" Each person asks the one behind and adds one to the answer. The last person, with nobody behind, says "zero": that is the base case. Without a last person, the question would never end.

The call stack and stack overflow

Each call that has not finished yet keeps its variables on the call stack, a region of memory with a limited size (often 1 MB on Windows and 8 MB on Linux by default). Recursion that goes too deep, or never reaches its base case, uses up the stack and the program crashes with a stack overflow (on Linux usually "Segmentation fault").

Careful: Recursive Fibonacci written as fib(n-1) + fib(n-2) recomputes the same values again and again and becomes extremely slow around n = 45. Use a loop, or remember answers you have already computed (memoisation, covered in the DSA module).

inline and constexpr functions (a quick note)

Small functions can be marked inline, which mainly means "this definition may appear in several files" (useful in headers). A constexpr function can be evaluated at compile time when its arguments are constants, for example constexpr int square(int n) { return n * n; } lets you write int grid[square(4)];.

Tip: Overload when the versions do the same job for different inputs (print an int, print a string). If the jobs differ, give them different names.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Overloading, default arguments and recursion · 1/6

Overloading · defaults · recursion

In this lesson: giving several functions one name, filling in default values, and functions that call themselves.

Prefer a video by a teacher? Find free videos on “c++ function overloading default arguments recursion tutorial” on YouTube ↗

In real life: A logging helper used across an app

Teams often write one writeLog function with overloads for text, numbers and errors, plus a default "INFO" level. Developers just call writeLog("Order placed") or writeLog("Payment failed", "ERROR") everywhere, and the output stays consistent.

cpp
#include <iostream>
#include <string>

void writeLog(const std::string& msg, const std::string& level = "INFO") {
    std::cout << "[" << level << "] " << msg << '\n';
}
void writeLog(int code) {
    writeLog("code " + std::to_string(code), "CODE");
}

int main() {
    writeLog("Order placed");               // [INFO] Order placed
    writeLog("Payment failed", "ERROR");    // [ERROR] Payment failed
    writeLog(404);                          // [CODE] code 404
}
Overloads plus a default argument keep calling code short.

Practice (0/4 done)

Task 1 · Question

Which pair is a valid overload?

Task 2 · Question

int power(int b, int e = 2) { int r = 1; for (int i = 0; i < e; ++i) r *= b; return r; } What is power(3) + power(2, 3)?

Task 3 · Question

int f(int n) { return n + f(n - 1); } What happens when you call f(3)?

Task 4 · Practice

Write a recursive function int power(int base, int exp) that computes base^exp, and a recursive bool isPalindrome(const std::string& s, int left, int right) that checks whether a word reads the same both ways (try "malayalam").

Quick quiz

Question 1

1.When does the compiler choose which overload to call?

Question 2

2.Which declaration is invalid?

Question 3

3.What are the two parts every recursive function needs?

Question 4

4.factorial(4) with factorial(n) = n * factorial(n - 1) and factorial(1) = 1 gives…

Question 5

5.Why is the simple recursive Fibonacci slow for n = 45?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

When does the compiler choose which overload to call?

Answer: At compile time, from the argument types

Overload resolution happens while compiling, based on the arguments in each call.

Which declaration is invalid?

Answer: void f(int a = 1, int b);

Parameters with defaults must come after all parameters without defaults.

What are the two parts every recursive function needs?

Answer: A base case and a recursive case that gets closer to it

Without a base case it never stops; without progress it never reaches the base case.

factorial(4) with factorial(n) = n * factorial(n - 1) and factorial(1) = 1 gives…

Answer: 24

4 × 3 × 2 × 1 = 24.

Why is the simple recursive Fibonacci slow for n = 45?

Answer: It recomputes the same smaller values a huge number of times

The number of calls grows exponentially. A loop or memoisation computes each value once.

What happens if a recursive function has no reachable base case?Related

Answer: It keeps calling itself until Python raises RecursionError

Every call adds a frame; with no base case the stack grows until the recursion limit (about 1,000 in Python) is hit.

From Recursion: functions that call themselves

What does every recursive function need to stop?Related

Answer: A base case

The base case answers the smallest input directly without calling itself.

From Higher-order functions and recursion

What usually happens when recursion goes too deep in C?Related

Answer: A stack overflow, typically a segmentation fault

The call stack runs out of space.

From Recursion

Deep recursion without a base case throws…Related

Answer: StackOverflowError

Each call uses stack space until it runs out.

From Methods: parameters, return values and overloading

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. This is the last topic of “Decisions, loops and functions”. The module exam comes next.
  2. Module 2 exam: Decisions, loops and functions · 12 questions · 20 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, References, pointers, arrays and strings. 42 topics left in the course before the final exam.

← Previous: Functions: declare, define, call and return