Functions & Overloading

Course 1 · Ch 3
Functions & Overloading
Something plain C structurally cannot do — and the linker trick that makes it possible

c1-5's functions had one name each, always. This chapter introduces the first genuinely new C++ capability that has no C equivalent at all — not a missing feature, a structural impossibility in C's own linking model.

Function Overloading

Multiple functions can share the same name, distinguished by their parameter types or count — the compiler picks the right one based on the actual arguments at each call site.

void print(int x) { std::cout << "int: " << x << std::endl; } void print(double x) { std::cout << "double: " << x << std::endl; } print(5); // calls print(int) print(5.0); // calls print(double)

C cannot do this at all. C compiles every function name directly to one plain, unmangled linker symbol — two functions named print in the same C program is simply a redefinition error, per c2-5's own linking material.

Name Mangling, Briefly

C++ solves this by encoding parameter types into the actual linker symbol name. print(int) and print(double) become genuinely different symbols under the hood — something like _Z5printi and _Z5printd.

$ nm program.o | grep print 0000000000000000 T _Z5printi 0000000000000010 T _Z5printd

This directly extends c2-5's own linker material: overloading isn't possible because the linker got smarter — it's possible because C++ generates different names for what looks, in source, like the same function name.

extern "C"

A real, practical need: calling a C library from C++, or being called from C code, requires plain, unmangled names. extern "C" tells the compiler to use C's own naming rules for specific declarations — this is exactly why standard C headers are internally wrapped in extern "C" when included from C++.

extern "C" { void legacy_c_function(int x); }

Default Arguments

A genuinely new feature: parameters can have default values, letting a function be called with fewer arguments than it declares.

void greet(std::string name, std::string greeting = "Hello") { std::cout << greeting << ", " << name << std::endl; } greet("Alice"); // uses the default greeting greet("Bob", "Hi"); // overrides it

C has no equivalent at all — the closest workaround is a variadic function, or several separately-named functions.

Overload Resolution Ambiguity

If a call could plausibly match more than one overload after implicit conversions, the compiler reports an ambiguous call error rather than guessing.

void print(int x); void print(long x); print(5L); // fine — an exact match for print(long) print('a'); // a char could convert to either int or long — genuinely ambiguous
ConceptCC++
Two functions, same nameredefinition errorvalid — overloading, resolved by parameter types
Linker symbol namesplain function namemangled — encodes parameter types
Fewer arguments than declarednot possible — variadic functions or multiple names onlydefault arguments
Name mangling is exactly why extern "C" exists
Two of this chapter's own concepts connect directly: extern "C" is needed specifically because name mangling would otherwise make a C++-compiled function unreachable from C's own, unmangled linker expectations.
Default arguments can only be omitted from the right
Only trailing parameters can have defaults, and only trailing arguments can be skipped — a middle parameter can never be omitted while a later one is still provided. This is a real, common syntax constraint worth internalizing early.

Coding Challenges

Challenge 1

Write two overloaded describe functions, one taking an int and one taking a std::string, each printing a different message. Call both from main and confirm the correct overload is selected each time.

📄 View solution
Challenge 2

Write a function power(int base, int exponent = 2) with a default argument, and call it once with both arguments and once with only the base, printing both results.

📄 View solution
Challenge 3

Explain precisely why C cannot support function overloading at all — tying your answer to how C's linker resolves symbol names — and why extern "C" is necessary when C++ code needs to interoperate with C.

📄 View solution

Chapter 3 Quick Reference

  • Overloading — same function name, different parameter types/count, resolved at the call site
  • Name mangling — the compiler encodes parameter types into the real linker symbol, making overloading possible
  • extern "C" — forces plain, unmangled C-style linkage for interop with C libraries/callers
  • Default arguments — trailing parameters only; can't skip a middle one and provide a later one
  • An ambiguous overload call is a compile error, never a silent guess
  • Next chapter: classes and objects — the leap beyond plain structs