Default parameters

2 minutes read

Default parameters in C++ provide a key advantage by allowing developers to call functions without supplying every argument. This versatility enhances usability by reducing the need for multiple overloaded functions.

For instance, when a function has optional parameters or those that often have the same value, default parameters make calling these functions simpler. You can still specify the parameters if needed.

This flexibility helps optimize your code by cutting down the number of parameters needed to call a function, resulting in cleaner code and fewer errors.

Default parameters

A default parameter is a function parameter with a preassigned value. If the user does not provide a value for the parameter when calling the function, the default value is used. If the user does provide a value, this value overrides the default.

Here are some examples of functions with default parameters:

#include <iostream>

// Function declaration with a default parameter
void greet(std::string name = "Guest") {
    std::cout << "Hello, " << name << "!" << std::endl;
}

int main() {
    greet(); 
    greet("John");
    return 0;
}

The result of our program:

Hello, Guest!
Hello, John!

⚠️ Default parameters can be defined either in the function prototype or upon initialization. However, you should declare default parameters in the function prototype rather than in the function definition.

It's good practice to set default parameters in the function prototype, usually located in a header file (.h), for more extensive projects:

#include <iostream>

// This function prototype may be in a header file (.h)
void logEvent(std::string event, int severity = 1);

void logEvent(std::string event, int severity) {
    std::cout << "Event: " << event << ", Severity: " << severity << std::endl;
}

int main() {
    logEvent("User login");
    logEvent("User logout", 2);
    return 0;
}

The result of our program:

Event: User login, Severity: 1
Event: User logout, Severity: 2

This method makes sure the default values are visible to any code that includes the header file where the function is declared, which helps document the interface clearly and prevents potential inconsistencies or confusion about the function's default behavior.

Multiple default parameters

You can have any number of default and normal parameters. This example shows how you can override none, some, or all default values when calling the function:

#include <iostream>

// Function with multiple default parameters
void setupGame(std::string game = "Chess", int players = 2) {
    std::cout << "Setting up a " << game;
    std::cout << " game for " << players;
    std::cout << " players." << std::endl;
}

int main() {
    setupGame(); // Uses both default values
    setupGame("Checkers"); // Overrides the first parameter, keeps second default
    setupGame("Poker", 4); // Overrides both default parameters
    return 0;
}

The result of our program:

Setting up a Chess game for 2 players.
Setting up a Checkers game for 2 players.
Setting up a Poker game for 4 players.

⚠️ Parameters with default values must come after all normal parameters.

Let's write a function to customize the game. It has general parameters, like game name and difficulty level, and default parameters for added settings, such as sound and the number of players.

#include <iostream>

void configureGame(
        std::string gameName, 
        int difficulty, 
        bool soundEnabled = true, 
        int players = 1) {
    std::cout << "Configuring game: " << gameName << std::endl;
    std::cout << "Difficulty level: " << difficulty << std::endl;
    std::cout << "Sound: " << (soundEnabled ? "Enabled" : "Disabled") << std::endl;
    std::cout << "Number of players: " << players << std::endl;
}

int main() {
    // Call with all parameters specified
    configureGame("Space Invaders", 3, false, 2);
    // Call with soundEnabled and players as default
    configureGame("Pac-Man", 2);
    // Call with soundEnabled overridden
    configureGame("Asteroids", 4, true);

    return 0;
}

It makes sense to put default parameters after normal ones because we typically specify essential parameters first. Doing this keeps things clear and avoids complicating the compiler's work, especially with overloaded functions.

Function overloading vs. default parameters

Adding default parameters does not affect the ability to overload functions. Combining default parameters with function overloading allows for more flexible function designs. However, this requires careful planning to avoid ambiguities that can confuse both the compiler and the programmer.

Here's an example that demonstrates both concepts in a single C++ program:

#include <iostream>

// Function with a default parameter
void displayMessage(std::string message, bool addNewLine = true) {
    std::cout << message;
    if (addNewLine) cout << std::endl;
}

// Overloaded function without the default parameter
void displayMessage(std::string message, std::string additionalMessage) {
    std::cout << message << " - " << additionalMessage << std::endl;
}

int main() {
    // Calls the function with the default parameter
    displayMessage("Hello, World!");

    // Calls the function with the default parameter explicitly set to false
    displayMessage("Hello, World!", false);
    std::cout << "(No newline above)" << std::endl;

    // Calls the overloaded function
    displayMessage("Hello", "World!");

    return 0;
}

The first displayMessage function includes one default parameter, addNewLine, which determines if a newline character follows the message.

The second displayMessage function is an overloaded variant that takes two string parameters without default values. This function joins message and additionalMessage with a hyphen and always adds a newline at the end.

⚠️ However, it's important to note that default parameters are not considered when determining the uniqueness of a function. Therefore, the following is not permissible:

void displayMessage(std::string message, bool addNewLine = true) {/*...*/}
void displayMessage(std::string message) {/*...*/}

These two function declarations will cause a compilation error. The first function displayMessage(std::string message, bool addNewLine = true) sets a default for the second parameter. This allows it to be called with just one std::string argument. The second function displayMessage(std::string message) appears identical when considering a call with a single std::string argument, leading to ambiguity.

When you call displayMessage with a single std::string argument, the compiler cannot decide which function to use because default parameters don't affect a function's signature in terms of overloading resolution.

Classes

In C++, you can use default parameters not only in functions but also in methods and when defining a class.

A class method in C++ is essentially a type of function defined within a class that operates on the class's data (members).

This approach lets you create objects with various initial states using the same constructor, making the code more flexible and user-friendly.

Consider the Book class, which has a constructor with default parameters:

#include <iostream>

class Book {
public:
    std::string title;
    std::string author;
    int pages;

    // Constructor with default parameters
    Book(std::string title = "Unknown", std::string author = "Unknown", int pages = 0) {
        this->title = title;
        this->author = author;
        this->pages = pages;
    }

    void displayInfo() {
        std::cout << "Book: " << title;
        std::cout << ", Author: " << author;
        std::cout << ", Pages: " << pages << std::endl;
    }
};

int main() {
    Book book1("1984", "George Orwell", 328); // Specifying all parameters
    Book book2("The Master and Margarita", "Mikhail Bulgakov"); // Omitting the pages parameter
    Book book3; // Using all default parameters

    book1.displayInfo();
    book2.displayInfo();
    book3.displayInfo();

    return 0;
}

The result of our program:

Book: 1984, Author: George Orwell, Pages: 328
Book: The Master and Margarita, Author: Mikhail Bulgakov, Pages: 0
Book: Unknown, Author: Unknown, Pages: 0

Conclusion

Default parameters in C++ create flexible and concise functions. By making some parameters optional, they simplify function interfaces and reduce the need for multiple overloaded functions.

Additionally, default parameters enhance code maintenance and readability. Since these default values are set at the function's declaration, any updates only need to happen in one place, making changes and modifications easier.

How did you like the theory?
Report a typo