C++ Default Arguments

Making functions more flexible with optional parameters

🎯 What are Default Arguments?

Default arguments allow you to call functions with fewer parameters than defined. If you don't provide a value, the function uses the default value you specified in the declaration.


// Function with default arguments
void greet(string name, string greeting = "Hello") {
    cout << greeting << ", " << name << "!" << endl;
}
// Can call: greet("Alice") or greet("Bob", "Hi")
                                    

Output:

greet("Alice") → Hello, Alice!
greet("Bob", "Hi") → Hi, Bob!

Default Arguments Features

🔧

Flexibility

Call functions with different parameter counts

func(a), func(a,b), func(a,b,c)
📝

Right to Left

Default values must be rightmost parameters

void func(int a, int b = 5, int c = 10)
🎨

Convenience

Reduces need for function overloading

// One function instead of multiple
⚙️

Configuration

Great for optional settings and parameters

connect(host, port = 80, timeout = 30)

🔹 Basic Default Arguments

Default arguments in C++ allow functions to have predefined values for parameters when no argument is provided. This simplifies function calls by letting you skip common values while retaining flexibility. For example, a function like void greet(string name, string city = "Unknown") can be called with just a name—the city defaults to “Unknown.” This reduces code duplication, improves readability, and is widely used in constructors, mathematical functions, and APIs to provide sensible defaults while allowing customization when needed.

#include <iostream>
#include <string>
using namespace std;

// Function with default arguments
void displayInfo(string name, int age = 25, string city = "Unknown") {
    cout << "Name: " << name << endl;
    cout << "Age: " << age << endl;
    cout << "City: " << city << endl;
    cout << "---" << endl;
}

int main() {
    // Different ways to call the function
    displayInfo("Alice");                    // Uses both defaults
    displayInfo("Bob", 30);                  // Uses city default
    displayInfo("Charlie", 28, "New York");  // No defaults used
    
    return 0;
}

Output:

Name: Alice
Age: 25
City: Unknown
---
Name: Bob
Age: 30
City: Unknown
---
Name: Charlie
Age: 28
City: New York
---

🔹 Mathematical Functions

Default arguments are especially useful in mathematical functions where certain parameters often remain constant. For instance, a power function double power(double base, int exponent = 2) can compute squares by default unless another exponent is specified. This approach minimizes repetitive code, enhances clarity, and supports common use cases like area calculations—where a default shape might be a square. Using defaults in math functions makes APIs intuitive and reduces the risk of errors from omitted parameters.

#include <iostream>
#include <cmath>
using namespace std;

// Power function with default exponent
double power(double base, double exponent = 2.0) {
    return pow(base, exponent);
}

// Area calculation with default shape (square)
double calculateArea(double length, double width = -1) {
    if (width == -1) width = length;  // Square if width not provided
    return length * width;
}

int main() {
    cout << "5^2 = " << power(5) << endl;           // Uses default exponent 2
    cout << "2^3 = " << power(2, 3) << endl;       // Custom exponent
    
    cout << "Square 4x4 = " << calculateArea(4) << endl;      // Square
    cout << "Rectangle 3x5 = " << calculateArea(3, 5) << endl; // Rectangle
    
    return 0;
}

Output:

5^2 = 25
2^3 = 8
Square 4x4 = 16
Rectangle 3x5 = 15

🔹 Constructor Default Arguments

Constructors in C++ often use default arguments to initialize objects with optional or missing data. For example, a Student class constructor might set default grade ‘A’ or age 18 if values aren’t provided. This allows flexible object creation while ensuring valid initial states. Default arguments in constructors streamline code, reduce overloaded constructors, and improve maintainability—especially in libraries or frameworks where object configurations vary widely but sensible defaults exist.

#include <iostream>
#include <string>
using namespace std;

class Student {
private:
    string name;
    int age;
    string grade;
    
public:
    // Constructor with default arguments
    Student(string n, int a = 18, string g = "A") 
        : name(n), age(a), grade(g) {}
    
    void display() {
        cout << "Student: " << name << ", Age: " << age 
             << ", Grade: " << grade << endl;
    }
};

int main() {
    // Different constructor calls
    Student s1("Alice");                    // Uses age=18, grade="A"
    Student s2("Bob", 20);                  // Uses grade="A"
    Student s3("Charlie", 19, "B");         // No defaults
    
    s1.display();
    s2.display();
    s3.display();
    
    return 0;
}

Output:

Student: Alice, Age: 18, Grade: A
Student: Bob, Age: 20, Grade: A
Student: Charlie, Age: 19, Grade: B

🔹 Rules and Best Practices

Important rules when using default arguments:

Rules:

  • Right-to-left: Default arguments must be rightmost
  • Declaration only: Specify defaults in function declaration, not definition
  • No gaps: Can't skip middle parameters when calling
  • Compile-time: Default values must be known at compile time
// ✅ CORRECT - defaults are rightmost
void func1(int a, int b = 5, int c = 10);

// ❌ WRONG - non-default after default
// void func2(int a = 1, int b, int c = 3);

// ✅ CORRECT - calling with defaults
func1(1);        // a=1, b=5, c=10
func1(1, 2);     // a=1, b=2, c=10
func1(1, 2, 3);  // a=1, b=2, c=3

// ❌ WRONG - can't skip middle parameter
// func1(1, , 3);  // This won't compile

🧠 Test Your Knowledge

Where must default arguments be positioned in a function parameter list?