Functions in C++
Learn how to define and use functions in C++ including parameters, default arguments, references, overloading, recursion, and lambdas with Docker-ready examples
Functions are the fundamental building blocks of structured C++ programs. They let you package a piece of logic behind a name, give it inputs (parameters), and hand back a result (a return value) — turning sprawling code into reusable, testable, and readable units.
As a multi-paradigm language, C++ gives functions an unusually rich feature set. Beyond the basics shared with C — declarations, definitions, and pass-by-value semantics — C++ adds references, default arguments, function overloading, and first-class functional tools like lambdas and std::function. This means the same add(a, b) idea can be expressed as a plain free function, an overloaded set of functions, or an inline lambda captured into a variable.
In this tutorial you’ll learn how to declare and define functions, pass arguments by value and by reference, use default parameters and overloading, understand variable scope, write recursive functions, and treat functions as values with lambdas and higher-order functions.
Defining and Calling Functions
A C++ function has a return type, a name, a parameter list, and a body. Functions are often declared first (a prototype, ending in a semicolon) so they can be called before their full definition appears later in the file.
Create a file named functions_basic.cpp:
| |
The prototypes at the top tell the compiler each function’s signature (name, parameter types, return type) so main() can call them even though their bodies come afterward. A void return type means the function returns no value.
Default Arguments, References, and Overloading
C++ lets a parameter have a default argument that is used when the caller omits it. Passing by reference (int&) lets a function modify the caller’s variable instead of working on a copy. And function overloading allows multiple functions to share one name, distinguished by their parameter types.
Create a file named functions_params.cpp:
| |
The compiler picks the correct multiply based on the argument types — integer arguments call the int version, floating-point arguments call the double version. Because doubleValue takes an int&, the change to n is visible back in main().
Scope and Recursion
Variables declared inside a function are local — they exist only while the function runs and are invisible to other functions. A function may also call itself, a technique called recursion, which is a natural fit for problems defined in terms of smaller subproblems.
Create a file named functions_recursion.cpp:
| |
Every recursive function needs a base case that returns without recursing, otherwise it would call itself forever. The local variable count lives only inside main() — the n parameters inside factorial and fibonacci are entirely separate.
Lambdas and Higher-Order Functions
Modern C++ (since C++11) treats functions as values. A lambda is an anonymous function you can store in a variable, and a higher-order function is one that takes or returns another function. The std::function wrapper can hold any callable with a matching signature.
Create a file named functions_modern.cpp:
| |
The [factor] capture clause copies the surrounding factor variable into the lambda so it can be used inside the body. Passing the [](int a, int b) { return a > b; } comparator to std::sort is idiomatic modern C++ — the algorithm calls your function for each comparison.
Running with Docker
| |
Expected Output
Running functions_basic.cpp:
add(3, 4) = 7
average(10, 20) = 15
Hello, Ada!
Running functions_params.cpp:
power(5) = 25
power(2, 10) = 1024
x after doubleValue = 42
multiply(3, 4) = 12
multiply(1.5, 2.0) = 3
Running functions_recursion.cpp:
factorial(5) = 120
fibonacci(10) = 55
Running functions_modern.cpp:
square(6) = 36
scale(10) = 30
applyTwice(square, 2) = 16
Sorted descending: 9 8 5 3 2 1
Key Concepts
- Declarations vs definitions — A prototype (
int add(int, int);) declares a function’s signature so it can be called before its body is defined later in the file. - Pass by value vs reference — Plain parameters receive copies, while reference parameters (
int&) let a function modify the caller’s variable directly; useconst&to pass large objects efficiently without copying. - Default arguments — Parameters can have default values, making them optional at the call site; defaults must come last in the parameter list.
- Function overloading — Multiple functions can share a name as long as their parameter types differ; the compiler resolves which to call from the argument types.
- Local scope — Variables and parameters declared inside a function exist only during that call and are isolated from other functions.
- Recursion — A function may call itself; every recursive function needs a base case to terminate.
- Lambdas — Anonymous functions written inline with
[](...) {...}can capture surrounding variables and be stored inautovariables. - Higher-order functions — With
std::functionand lambdas, functions become first-class values you can pass to and return from other functions, powering the standard library’s algorithms.
Comments
Loading comments...
Leave a Comment