Lesson 6 • Intermediate
Functions
Create reusable, organized code blocks with functions — the building blocks of every professional C++ program.
What You'll Learn
- ✓ Defining and calling functions
- ✓ Default parameters and overloading
- ✓ Pass by value vs reference vs const reference
- ✓ Recursion and base cases
What Are Functions?
A function is a named block of code that performs a specific task. Think of functions like recipes — you define the steps once, then call them whenever you need that dish.
Functions help you follow the DRY principle (Don't Repeat Yourself). Instead of copying code, you write it once in a function and call it many times.
Function Anatomy
returnType functionName(paramType param1, paramType param2) {
// function body — the code that runs
return value; // send a result back (omit for void)
}| Part | Purpose | Example |
|---|---|---|
| Return type | What the function gives back | int, double, void |
| Name | Identifier to call it | calculateArea |
| Parameters | Input values | (double w, double h) |
| Body | The logic/code | return w * h; |
Basic Functions
Create void, returning, and boolean functions
#include <iostream>
using namespace std;
// Function with no return value (void)
void greet(string name) {
cout << "Hello, " << name << "! Welcome to C++." << endl;
}
// Function with return value
int add(int a, int b) {
return a + b;
}
// Function with multiple parameters
double calculateBMI(double weight, double height) {
return weight / (height * height);
}
// Function returning a bool
bool isEven(int number) {
return number % 2 == 0;
}
int main() {
// Calling void fu
...Default Parameters & Overloading
Use defaults and create overloaded functions with same names
#include <iostream>
#include <string>
using namespace std;
// Default parameters — must be rightmost
double calculateArea(double length, double width = 1.0) {
return length * width;
}
// Function overloading — same name, different parameters
int maxOf(int a, int b) {
return (a > b) ? a : b;
}
double maxOf(double a, double b) {
return (a > b) ? a : b;
}
int maxOf(int a, int b, int c) {
return maxOf(maxOf(a, b), c);
}
// Overloaded print function
void display(int value) {
...Pass by Value vs Reference
How you pass arguments determines whether the function can modify the original data.
| Method | Syntax | Modifies Original? | Use When |
|---|---|---|---|
| By value | f(int x) | ❌ No (copy) | Small types, safety |
| By reference | f(int &x) | ✅ Yes | Need to modify original |
| By const ref | f(const int &x) | ❌ No (read-only) | Large objects, efficiency |
Think of it this way: by value is like giving someone a photocopy — they can scribble on it without affecting your original. By reference is like handing over the original document itself.
Pass by Value vs Reference
See the difference between copies and references, plus swap and multi-return
#include <iostream>
#include <vector>
using namespace std;
// Pass by VALUE — makes a copy (original unchanged)
void doubleValue(int x) {
x *= 2;
cout << "Inside (value): " << x << endl; // Changed copy
}
// Pass by REFERENCE — modifies the original
void doubleRef(int &x) {
x *= 2;
cout << "Inside (ref): " << x << endl; // Changed original
}
// Pass by CONST reference — read-only, no copy
void printVector(const vector<int> &v) {
cout << "Vector: ";
for (int num : v)
...Recursion
Implement factorial, Fibonacci, power, and digit sum recursively
#include <iostream>
using namespace std;
// Factorial — classic recursion
int factorial(int n) {
if (n <= 1) return 1; // Base case
return n * factorial(n - 1); // Recursive case
}
// Fibonacci sequence
int fibonacci(int n) {
if (n <= 0) return 0;
if (n == 1) return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
}
// Power function
double power(double base, int exp) {
if (exp == 0) return 1.0;
if (exp < 0) return 1.0 / power(base, -exp);
return base * po
...Common Mistakes
⚠️ Forgetting return: Non-void functions must return a value on all paths, or you get undefined behavior.
⚠️ Wrong parameter order: Default parameters must come last: f(int a, int b = 5) is valid, f(int a = 5, int b) is not.
⚠️ Infinite recursion: Every recursive function needs a base case. Without one, your program crashes from stack overflow.
⚠️ Returning local references: Never return a reference to a local variable — it's destroyed when the function ends.
Pro Tips
💡 Use const& for large objects: Passing string, vector, or custom objects by const& avoids expensive copies.
💡 One function, one job: Each function should do exactly one thing well. If it's doing too much, split it up.
💡 Forward declarations: Declare functions before main() and define them after for cleaner code organization.
📋 Quick Reference
| Concept | Syntax |
|---|---|
| Void function | void greet() { } |
| Return value | int add(int a, int b) { return a+b; } |
| Default param | void f(int x, int y = 10) |
| By reference | void f(int &x) |
| Const reference | void f(const string &s) |
| Overloading | Same name, different params |
Lesson Complete!
You now know how to create, call, and organize functions in C++. Next up: Arrays & Vectors — store collections of data efficiently.
Sign up for free to track which lessons you've completed and get learning reminders.