C++ Default Arguments: How to Give Function Parameters Default Values
Sometimes a function parameter almost always gets the same value. Rather than forcing the caller to repeat it every time, C++ lets you declare a default value right in the function signature. If the caller provides an argument, that value is used. If not, the default kicks in.
Basic Syntax
Declare a default by writing = value after the parameter name:
#include <iostream>
#include <string>
void greet(std::string name = "World") {
std::cout << "Hello, " << name << "!\n";
}
int main() {
greet("Alice"); // Hello, Alice!
greet(); // Hello, World!
return 0;
}
The second call uses the default value "World" because no argument was passed.
Multiple Default Arguments
You can give defaults to multiple parameters. The rule is: defaults must be at the end of the list — you can’t have a non-default parameter after a default one.
#include <iostream>
void drawBox(int width, int height = 5, char fill = '*') {
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
std::cout << fill;
}
std::cout << "\n";
}
}
int main() {
drawBox(4); // width=4, height=5, fill='*'
std::cout << "\n";
drawBox(3, 2); // width=3, height=2, fill='*'
std::cout << "\n";
drawBox(3, 2, '#'); // width=3, height=2, fill='#'
return 0;
}
Output:
****
****
****
****
****
***
***
###
###
This works because you always provide the required parameter (width) and optionally override the defaults.
The “Trailing Defaults” Rule
This is valid:
void example(int a, int b = 10, int c = 20); // fine
This is NOT valid:
void example(int a = 5, int b, int c = 20); // error — b has no default but follows a
Think of it like a queue: once you start adding defaults, every parameter that follows must also have a default.
Default Arguments in Header Files
If you split your code into header (.h) and implementation (.cpp) files, declare the defaults only in the header — not in both places. Putting them in both causes a compiler error.
// myFunc.h
void connect(std::string host, int port = 8080, bool secure = false);
// myFunc.cpp
void connect(std::string host, int port, bool secure) {
// no defaults here
}
Default Arguments vs Function Overloading
Both achieve similar results, but the right choice depends on your situation:
// Using defaults — single function, same logic
void log(std::string msg, bool newline = true) {
std::cout << msg;
if (newline) std::cout << "\n";
}
// Using overloading — separate logic per version
void log(std::string msg) { std::cout << msg << "\n"; }
void log(std::string msg, int level) {
std::cout << "[" << level << "] " << msg << "\n";
}
Use defaults when the function body is the same and you just want optional parameters. Use function overloading when different argument types require genuinely different behaviour.
Practical Example: A Configurable Timer
#include <iostream>
void startTimer(int seconds, bool verbose = false, std::string label = "Timer") {
if (verbose) {
std::cout << label << " starting: " << seconds << "s\n";
}
// (actual timer logic would go here)
if (verbose) {
std::cout << label << " finished.\n";
}
}
int main() {
startTimer(10); // quiet mode
startTimer(5, true); // verbose, default label
startTimer(3, true, "Download timer"); // fully specified
return 0;
}
Related Articles
- C++ Functions Tutorial: How to Write and Use Functions
- C++ Function Overloading: Same Name, Different Parameters Explained
- C++ Header Files Explained for Beginners
- C++ Pass by Value vs Pass by Reference
Take Your C++ Further
If you’re looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you’re a complete beginner or looking to solidify your understanding. Just $19.