functions
In C++, functions are defined by specifying a return type, function name, and parameter list. Functions let you group logic into reusable units. Parameters can be passed by value or by reference, and default arguments allow optional parameters at the call site.
Syntax
// Return type, function name, parameters, and body
int add(int a, int b) {
return a + b;
}
// void function: no return value
void greet(std::string name) {
std::cout << name << std::endl;
}
// Pass by reference: & allows modifying the caller's variable
void doubleValue(int& x) {
x *= 2;
}
// const reference: avoids copy without allowing modification
void printName(const std::string& name) {
std::cout << name << std::endl;
}
// Default argument: can be omitted at the call site
int calcDamage(int base, int multiplier = 1) {
return base * multiplier;
}
// Forward declaration: declares a function before its definition
int square(int n);
// Recursive function: calls itself; must have a base case
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
Syntax Reference
| Syntax | Description |
|---|---|
| ReturnType name(params) { } | Defines a function. Groups logic under a name for reuse. |
| void name(params) { } | Defines a function that returns nothing. Used for output or side effects. |
| Type& param | Pass by reference. The function can modify the caller's variable directly. |
| const Type& param | Const reference. Avoids copying large objects while preventing modification. |
| Type param = default | Default argument. When omitted at the call site, the default value is used. |
| ReturnType name(params); | Forward declaration. Allows calling a function before its definition appears. |
| Calls itself inside body | Recursive function. Requires a base case to prevent infinite recursion. |
Sample Code
jujutsu.cpp
// jujutsu.cpp
// Comprehensive function sample using Jujutsu Kaisen characters.
// Demonstrates forward declaration, void functions, pass-by-reference,
// const reference, default arguments, and recursion.
#include <iostream>
#include <string>
// Forward declaration
int calcCursedDamage(int base, int multiplier);
// void function: print the technique name
void activateTechnique(const std::string& sorcerer, const std::string& technique) {
std::cout << sorcerer << " activates [" << technique << "]." << std::endl;
}
// Pass by value: returns base * multiplier
int calcCursedDamage(int base, int multiplier) {
return base * multiplier;
}
// Default argument: multiplier defaults to 1
int calcCursedEnergy(int power, int multiplier = 1) {
return power * multiplier;
}
// Pass by reference: subtracts damage from hp directly
void applyDamage(int& hp, int damage) {
hp -= damage;
if (hp < 0) hp = 0;
}
// Const reference: prints status without copying strings
void printStatus(const std::string& name, int hp, int cursedEnergy) {
std::cout << "[" << name << "] HP: " << hp
<< " Cursed Energy: " << cursedEnergy << std::endl;
}
// Recursive function: accumulates base damage n times
int recursiveDamage(int base, int n) {
if (n <= 0) return 0;
return base + recursiveDamage(base, n - 1);
}
int main() {
std::string s1 = "Itadori Yuji";
std::string s2 = "Fushiguro Megumi";
int hp1 = 300, hp2 = 250;
int energy1 = 150, energy2 = 120;
std::cout << "=== Battle Start ===" << std::endl;
printStatus(s1, hp1, energy1);
printStatus(s2, hp2, energy2);
std::cout << std::endl;
activateTechnique(s1, "Divergent Fist");
int dmg1 = calcCursedDamage(80, 2);
int cost1 = calcCursedEnergy(80, 2);
applyDamage(hp2, dmg1);
energy1 -= cost1;
std::cout << " Damage: " << dmg1 << " Energy cost: " << cost1 << std::endl;
std::cout << std::endl;
activateTechnique(s2, "Divine Dog: Totality");
int dmg2 = calcCursedDamage(50, 1);
int cost2 = calcCursedEnergy(50); // default multiplier = 1
applyDamage(hp1, dmg2);
energy2 -= cost2;
std::cout << " Damage: " << dmg2 << " Energy cost: " << cost2 << std::endl;
std::cout << std::endl;
activateTechnique(s1, "Divergent Fist (x3)");
int totalDmg = recursiveDamage(60, 3);
applyDamage(hp2, totalDmg);
std::cout << " Total damage (recursive): " << totalDmg << std::endl;
std::cout << std::endl;
std::cout << "=== Battle End ===" << std::endl;
printStatus(s1, hp1, energy1);
printStatus(s2, hp2, energy2);
return 0;
}
g++ -std=c++17 jujutsu.cpp -o jujutsu ./jujutsu === Battle Start === [Itadori Yuji] HP: 300 Cursed Energy: 150 [Fushiguro Megumi] HP: 250 Cursed Energy: 120 Itadori Yuji activates [Divergent Fist]. Damage: 160 Energy cost: 160 Fushiguro Megumi activates [Divine Dog: Totality]. Damage: 50 Energy cost: 50 Itadori Yuji activates [Divergent Fist (x3)]. Total damage (recursive): 180 === Battle End === [Itadori Yuji] HP: 250 Cursed Energy: -10 [Fushiguro Megumi] HP: 0 Cursed Energy: 70
Common Mistake 1: Missing base case in recursion
A recursive function without a base case calls itself indefinitely, causing a stack overflow. Always include a termination condition.
// NG: no base case — infinite recursion
int badFactorial(int n) {
return n * badFactorial(n - 1);
}
OK: add a base case to stop recursion.
// OK:
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
Common Mistake 2: Placing a default argument before a non-default argument
Default arguments must appear at the end of the parameter list. Placing a non-default parameter after a default one is a compile error.
// NG: compile error — non-default parameter follows a default one
int calcDamage(int base = 10, int multiplier) {
return base * multiplier;
}
OK: put default arguments last.
// OK:
int calcDamage(int multiplier, int base = 10) {
return base * multiplier;
}
Overview
C++ functions are defined in the form ReturnType name(params) { body }. Parameters can be passed by value (a copy is made) or by reference (Type&, modifying the caller's variable). When a large object should be read without copying, use const Type& (const reference). Default arguments give parameters an initial value used when the argument is omitted, enabling flexible interfaces. A forward declaration (prototype) allows calling a function before its body is defined. Recursive functions call themselves and must include a base case to avoid infinite recursion. They are commonly used for factorial computation, tree traversal, and divide-and-conquer algorithms.
If you find any errors or copyright issues, please contact us.