cpp
Function Overloading
03_Function_Overloading⚙️cpp
/**
* ============================================================
* C++ FUNCTION OVERLOADING
* ============================================================
*
* This file covers:
* - Function overloading basics
* - Overloading rules
* - Ambiguity issues
* - Best practices
*
* Compile: g++ -std=c++17 -Wall 01_overloading.cpp -o overloading
* Run: ./overloading
*
* ============================================================
*/
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// ============================================================
// FUNCTION OVERLOADING - SAME NAME, DIFFERENT PARAMETERS
// ============================================================
/*
* Function overloading allows multiple functions with the same name
* but different parameter lists. The compiler determines which
* function to call based on the arguments provided.
*
* What can differ:
* - Number of parameters
* - Types of parameters
* - Order of parameters (if types differ)
*
* What CANNOT differ (for overloading):
* - Return type alone
* - Parameter names
*/
// ============================================================
// OVERLOADED print() FUNCTIONS
// ============================================================
// Print integer
void print(int value) {
cout << "int: " << value << endl;
}
// Print double
void print(double value) {
cout << "double: " << value << endl;
}
// Print string
void print(const string& value) {
cout << "string: " << value << endl;
}
// Print character
void print(char value) {
cout << "char: " << value << endl;
}
// Print boolean
void print(bool value) {
cout << "bool: " << (value ? "true" : "false") << endl;
}
// Print with a label
void print(const string& label, int value) {
cout << label << ": " << value << endl;
}
// ============================================================
// OVERLOADED add() FUNCTIONS
// ============================================================
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
string add(const string& a, const string& b) {
return a + b;
}
// Three parameters
int add(int a, int b, int c) {
return a + b + c;
}
// ============================================================
// OVERLOADED max() FUNCTIONS
// ============================================================
int max(int a, int b) {
return (a > b) ? a : b;
}
double max(double a, double b) {
return (a > b) ? a : b;
}
int max(int a, int b, int c) {
return max(max(a, b), c); // Uses the two-parameter version
}
// ============================================================
// OVERLOADED area() FUNCTIONS
// ============================================================
// Area of square
double area(double side) {
cout << " (Square)" << endl;
return side * side;
}
// Area of rectangle
double area(double length, double width) {
cout << " (Rectangle)" << endl;
return length * width;
}
// Area of circle (using different parameter type)
double area(double radius, bool isCircle) {
if (isCircle) {
cout << " (Circle)" << endl;
return 3.14159 * radius * radius;
}
return area(radius); // Fall back to square
}
// ============================================================
// MAIN FUNCTION
// ============================================================
int main() {
cout << "============================================" << endl;
cout << " C++ FUNCTION OVERLOADING" << endl;
cout << "============================================" << endl << endl;
// ========================================================
// PART 1: BASIC OVERLOADING
// ========================================================
cout << "--- PART 1: BASIC OVERLOADING ---" << endl << endl;
// Compiler chooses the right function based on argument types
print(42); // Calls print(int)
print(3.14); // Calls print(double)
print("Hello"); // Calls print(const string&)
print('A'); // Calls print(char)
print(true); // Calls print(bool)
cout << endl;
// ========================================================
// PART 2: DIFFERENT NUMBER OF PARAMETERS
// ========================================================
cout << "--- PART 2: DIFFERENT PARAMETER COUNT ---" << endl << endl;
cout << "add(5, 3) = " << add(5, 3) << endl;
cout << "add(5, 3, 2) = " << add(5, 3, 2) << endl;
// With label
print("Age", 25); // Calls print(string, int)
print("Score", 100);
cout << endl;
// ========================================================
// PART 3: DIFFERENT PARAMETER TYPES
// ========================================================
cout << "--- PART 3: DIFFERENT PARAMETER TYPES ---" << endl << endl;
cout << "add(5, 3) = " << add(5, 3) << endl;
cout << "add(5.5, 3.3) = " << add(5.5, 3.3) << endl;
cout << "add(\"Hello\", \"World\") = " << add("Hello", " World") << endl;
cout << "\nmax(10, 20) = " << max(10, 20) << endl;
cout << "max(3.14, 2.71) = " << max(3.14, 2.71) << endl;
cout << "max(5, 10, 7) = " << max(5, 10, 7) << endl;
cout << endl;
// ========================================================
// PART 4: PRACTICAL EXAMPLE - AREA CALCULATION
// ========================================================
cout << "--- PART 4: AREA CALCULATIONS ---" << endl << endl;
cout << "Area of square (5): " << area(5.0) << endl;
cout << "Area of rectangle (4x6): " << area(4.0, 6.0) << endl;
cout << "Area of circle (r=3): " << area(3.0, true) << endl;
cout << endl;
// ========================================================
// PART 5: TYPE CONVERSION AND RESOLUTION
// ========================================================
cout << "--- PART 5: TYPE CONVERSION ---" << endl << endl;
// Implicit conversions can affect overload resolution
print(10); // Exact match: print(int)
print(10.5); // Exact match: print(double)
print(10.5f); // float → double conversion: print(double)
// Be careful with implicit conversions!
// print(10L); // long - might be ambiguous depending on overloads
// Character literals
print('X'); // Exact match: print(char)
print(65); // Exact match: print(int), not char!
cout << endl;
// ========================================================
// PART 6: RULES AND BEST PRACTICES
// ========================================================
cout << "--- PART 6: RULES AND BEST PRACTICES ---" << endl << endl;
cout << "OVERLOADING RULES:" << endl;
cout << "─────────────────────────────────────────" << endl;
cout << "✓ Can differ in number of parameters" << endl;
cout << "✓ Can differ in parameter types" << endl;
cout << "✓ Can differ in parameter order (if types differ)" << endl;
cout << "✗ Cannot differ ONLY in return type" << endl;
cout << "✗ Cannot differ ONLY in parameter names" << endl;
cout << "\nBEST PRACTICES:" << endl;
cout << "─────────────────────────────────────────" << endl;
cout << "• Keep overloaded functions semantically similar" << endl;
cout << "• Avoid too many overloads (confusing)" << endl;
cout << "• Be cautious with implicit conversions" << endl;
cout << "• Consider templates for type-generic functions" << endl;
cout << "• Document overloaded functions clearly" << endl;
cout << endl;
// ========================================================
// PART 7: WHAT DOESN'T WORK
// ========================================================
cout << "--- PART 7: COMMON MISTAKES ---" << endl << endl;
cout << "The following would NOT compile:" << endl;
cout << "─────────────────────────────────────────" << endl;
cout << "// Different return type only - ERROR!" << endl;
cout << "// int getValue() { return 1; }" << endl;
cout << "// double getValue() { return 1.0; }" << endl;
cout << endl;
cout << "// Different parameter names only - ERROR!" << endl;
cout << "// void func(int x) { }" << endl;
cout << "// void func(int y) { } // Same as above!" << endl;
cout << endl;
cout << "// Default arguments can cause ambiguity" << endl;
cout << "// void func(int x, int y = 0) { }" << endl;
cout << "// void func(int x) { } // Ambiguous call: func(5)" << endl;
cout << endl;
cout << "============================================" << endl;
cout << "FUNCTION OVERLOADING SUMMARY:" << endl;
cout << "============================================" << endl;
cout << "• Same name, different parameters" << endl;
cout << "• Compiler picks best match at compile time" << endl;
cout << "• Return type alone doesn't distinguish" << endl;
cout << "• Be careful with implicit type conversions" << endl;
cout << "• Use for related operations on different types" << endl;
cout << "============================================" << endl;
return 0;
}
// ============================================================
// EXERCISES:
// ============================================================
/*
* 1. Create overloaded functions to calculate the average of:
* - Two integers
* - Three integers
* - A vector of integers
*
* 2. Create overloaded functions to find minimum:
* - Of two values (int, double, string versions)
* - Of three values
* - Of an array
*
* 3. Create overloaded display() functions that:
* - Display an integer with optional label
* - Display a vector with optional separator
* - Display a 2D array with formatting
*
* 4. Create overloaded concatenate() functions for:
* - Two strings
* - String and integer
* - String and double (with precision parameter)
*/