- References
- Function Overloading
- Default Function Arguments
- Inline Function
- Dynamic Memory Allocation
- Placement New
- nullptr
- Namespaces
- Type Aliases
- Enum classes
- constexpr
- static_assert
- mutable Keyword
- auto Keyword
- Smart Pointers
- Basics of Classes
- Constructors
- Destructors
- Operator Overloading
- Copy Semantics
- Move Semantics
- Composition, RAII & Ownership
- Inheritance
- Polymorphism
- Abstraction
- Encapsulation
- Template
- Static Memory
- Friend Function
- this Pointer
- Function Pointer
- Lambdas and Callback Management
- Union
Function Overloading (Compile-Time Polymorphism)

In C, every function must have a unique name (e.g., print_int, print_string, print_float).
In C++, Function Overloading allows multiple functions to share the same name, provided they have different parameter lists (number or types of arguments).
The compiler decides which function to call at compile time based on the arguments passed. This is known as Static Resolution.
Syntax & Usage
1. Basic Overloading
You can define multiple versions of a log() function to handle different data types cleanly.
void log(int val) {
// Code to print integer to UART
}
void log(const char* msg) {
// Code to print string to UART
}
void log(double val) {
// Code to print float to UART
}
// Usage
log(100); // Calls log(int)
log("Error"); // Calls log(const char*)
log(3.14); // Calls log(double)2. Overloading by Number of Arguments
Useful for providing default behaviors or extended options.
// Initialize timer with default prescaler
void timer_init(int period_ms);
// Initialize timer with specific prescaler
void timer_init(int period_ms, int prescaler);How It Works: Name Mangling
C++ supports this by "mangling" the function names. The compiler adds information about the parameters to the internal symbol name.
| Function Declaration | Internal Linker Symbol (Example) |
|---|---|
void func(int) | _Z4funci |
void func(double) | _Z4funcd |
void func(int, int) | _Z4funcii |
Note: This is why you must use extern "C" when calling C functions from C++ (to stop mangling).
Relevance in Embedded/Firmware
1. Cleaner HAL/Driver APIs
Instead of remembering uart_send_byte, uart_send_array, uart_send_string, you simply use uart.send(). The compiler picks the right driver function for you.
serial.print(10); // Easy to read
serial.print("Hello"); // Consistent interface2. Constructor Overloading
A peripheral driver can have multiple constructors to support different initialization modes (e.g., one for default settings, one for custom pins).
// Default I2C (uses standard pins)
I2C_Driver sensor_bus;
// Remapped I2C (uses custom pins)
I2C_Driver sensor_bus(PB_9, PB_8); 3. Type-Safe Alternatives to void*
In C, generic handlers often take void* and size, requiring unsafe casting. Overloading lets you write specific, type-safe handlers for int, struct, or float without casting.
Common Pitfalls (Practical Tips)
| Pitfall | Details |
|---|---|
| ❌ Return Type Only | You cannot overload based only on return type.
|
| ❌ Implicit Conversions | Passing Fix: Use |
| ❌ Code Bloat | Remember: Overloaded functions are separate functions in Flash memory. They share a name, not code. If you implement logic 3 times, you use 3x the flash. Fix: Have all overloads call a single private "worker" function to share logic. |
| ✅ Default Arguments | Sometimes using Default Arguments (void func(int x, int y=0)) is better than overloading if the code logic is identical. |
❌ extern "C" Conflicts | You cannot overload functions inside an extern "C" block because C does not support name mangling. |
Concept understood? Let's apply and learn for real