C++ Function Overloading
Lesson outline
What is Function Overloading?
Function overloading allows you to create multiple functions with the same name but different parameters in C++. The compiler determines which function to call based on the arguments passed.
This enables you to use the same function name for similar operations that work with different data types.
Basic Syntax
Key Rules
- Overloaded functions must differ in their parameter lists (number, type, or order of parameters).
- Return type alone is not sufficient to overload a function.
- Functions can be overloaded in the same scope (namespace or class). A derived class can also expose base-class overloads with a
using Base::name;declaration.
| Valid Overloading | Invalid Overloading |
|---|---|
| Different parameter types (including reference vs const reference, pointer vs pointer-to-const) | Different return types only |
| Different number of parameters | Different parameter names only |
| Different parameter order (when types differ) | Different default arguments only (defaults are not part of the signature) |
Different cv/ref qualifiers on member functions (e.g., int f() const; vs int f();, or void g() &; vs void g() &&;) | Different exception specification / noexcept only |
Note: top-level const on a by-value parameter does NOT make a new overload (e.g., int f(int) vs int f(const int) is the same) | — |
Practical Example
Const, References, and Member Overloads
Overloads can differ by reference/pointer constness (e.g., void f(int&) vs void f(const int&), void f(int*) vs void f(const int*)).
Top-level const on a by-value parameter does NOT create a distinct overload (e.g., int f(int) and int f(const int) are the same).
For member functions, const/volatile qualifiers and ref-qualifiers (&, &&) participate in overloading (e.g., int get() const; vs int get();, void use() &; vs void use() &&;).
Common Pitfalls
- Ambiguous calls when the compiler can't determine which overload to use (e.g., passing a literal or
nullptrthat matches multiple candidates). - Hidden overloads when derived class functions hide base class functions with the same name; fix by adding
using Base::name;in the derived class to bring base overloads into the overload set. - Performance impact from implicit conversions when calling overloaded functions; prefer exact matches, or use templates to avoid unnecessary conversions.
Best Practices
- Use overloading for functions that perform conceptually similar operations.
- Keep overloads consistent in behavior and semantics.
- Document all overloads clearly.
- Prefer templates when the logic is identical across types.
- Avoid overload sets that differ only subtly (which encourage implicit conversions or ambiguity).