Skip to Content
Course content
Click on the "Edit" button in the top corner of the screen to edit your slide content.

I want to show you something that trips up almost every C++ developer when they first start splitting their code into header files and implementation files. It's a subtle compiler error that feels like the computer is lying to you.

// GameUtils.h
void spawnEnemy(std::string name, int health);

// GameUtils.cpp
void spawnEnemy(std::string name, int health = 100) {
    // Logic to place enemy in the world...
}

// main.cpp
int main() {
    spawnEnemy("Goblin"); // Error: too few arguments to function call
    return 0;
}

The 'Too Few Arguments' Headache

If you try to compile this, your compiler is going to scream at you in main.cpp. It will tell you that spawnEnemy expects two arguments, but you only gave it one. You'll probably look at GameUtils.cpp, see that health = 100 is right there, and wonder why the compiler is ignoring it.

Here is the deal: the compiler processes files individually. When it's compiling main.cpp, it doesn't look at the implementation in the .cpp file; it only looks at the declaration in the .h file. Since the header says spawnEnemy requires a name and health, the compiler assumes you've made a mistake. It has no idea that a default value exists because you hid it in the implementation file.

Moving Defaults to the Declaration

To fix this, you have to move the default value to the function declaration (the prototype). This tells any file including that header exactly what the default is so it can "fill in the blank" during compilation.

// GameUtils.h
// The default goes here!
void spawnEnemy(std::string name, int health = 100);

// GameUtils.cpp
// Do NOT repeat the default value here
void spawnEnemy(std::string name, int health) {
    // Logic to place enemy in the world...
}

Now, when main.cpp sees spawnEnemy("Goblin"), the compiler checks the header, sees that health is optional and defaults to 100, and effectively rewrites your call to spawnEnemy("Goblin", 100) behind the scenes. Note that I removed the = 100 from the .cpp file; C++ doesn't allow you to define the default in both places, as that would be redundant and potentially conflicting.

The Trap of Out-of-Order Arguments

There's one more rule you need to keep in mind. Default arguments must always be the rightmost parameters. You can't have a "gap" in your arguments.

Imagine you tried to do this:

void setPlayerPosition(int x = 0, int y, int z = 0); // This will NOT compile

The compiler would have no idea what to do if you called setPlayerPosition(10, 20). Does the 20 go to y (meaning x stays 0), or does the 10 go to x and 20 go to z (meaning y is missing)? To avoid this ambiguity, C++ requires that once you provide a default value for one parameter, every single parameter to the right of it must also have a default value.

I personally use default arguments sparingly. They're great for optional configuration, but if you find yourself with ten different default arguments, you're probably better off creating a Config struct to pass into the function instead. It keeps the call sites much cleaner.




📋 Practical Task

Building a Flexible System Logger

You are tasked with creating a logging utility for a software project. The goal is to allow developers to log messages with different severity levels, but since "Info" is the most common level, it should be the default.

Requirements:

  • Create a function called logMessage.
  • It should take two parameters: a std::string message and an int level.
  • The level parameter should have a default value of 1 (representing "Info").
  • The function should print the level and the message to the console (e.g., "[Level 1] System started").
  • In your main function, demonstrate two calls: one where you provide only the message, and one where you override the default level to 3 (representing "Error").
Rating
0 0

There are no comments for now.

to be the first to leave a comment.