Paramclasses Academy - Blog

Tutorials Details

←
Post 8 of 13
→

what is Functions in C++

what is Functions in C++

October 15, 2026

A function is a reusable block of code designed to perform a specific task. Instead of writing the same logic repeatedly, you can place it inside a function and call it whenever needed.

Functions are essential for writing organized, reusable, readable, and maintainable C++ programs.

Learning objectives

By the end of this module, you should be able to:

  • Understand why functions are useful.

  • Declare, define, and call functions.

  • Pass arguments using parameters.

  • Return values from functions.

  • Understand void functions.

  • Distinguish pass by value from pass by reference.

  • Use default arguments and function overloading.

  • Organize a program into multiple functions.

    Estimated time: 75–100 minutes

    Prerequisites: Variables, conditions, loops, arrays, and strings

1. What is a function?

Suppose a program needs to calculate the sum of two numbers several times. Without functions, you might repeat the same addition logic in multiple places.

With a function, you write the logic once and reuse it.

How a function works

Input arguments

For example: 10 and 20

Function: add(10, 20)

Executes the function's instructions

Return value: 30

Benefits of functions

  • Reusability: Write logic once and call it multiple times.

  • Modularity: Break a large program into smaller tasks.

  • Readability: Give meaningful names to operations.

  • Testing: Test individual parts more easily.

  • Maintenance: Update one function instead of changing repeated code.

2. Basic function syntax

A function commonly consists of a declaration, a definition, and one or more calls.

General syntax

returnType functionName(parameterList) {
    // Function body
    return value;
}

Component

Meaning

returnType

Type of value returned, such as int or double

functionName

Name used to call the function

parameterList

Inputs the function receives

Function body

Statements that perform the task

return

Sends a result back to the caller when applicable

Example: A simple function

#include <iostream>
using namespace std;

int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(10, 20);

    cout << "Sum = " << result;

    return 0;
}

Output

Sum = 30

How it works:

  1. int add(int a, int b) defines a function that receives two integers.

  2. add(10, 20) calls the function with arguments 10 and 20.

  3. Inside the function, a + b evaluates to 30.

  4. return sends 30 back to the caller.

  5. The returned value is stored in result and printed.

3. Function declaration, definition, and call

These three concepts are closely related but have different purposes.

A. Function declaration

A declaration tells the compiler a function's name, return type, and parameter types.

int add(int a, int b);

This is also called a function prototype. Parameter names can be omitted:

int add(int, int);

B. Function definition

A definition provides the actual implementation.

int add(int a, int b) {
    return a + b;
}

C. Function call

A call executes the function.

int result = add(5, 7);

The result is 12.

Complete example using a declaration

#include <iostream>
using namespace std;

int multiply(int a, int b);  // Declaration

int main() {
    cout << multiply(4, 5);  // Function call
    return 0;
}

int multiply(int a, int b) { // Definition
    return a * b;
}

Output

20

The declaration allows main() to call multiply() before its definition appears later in the file.

4. Functions with parameters

A parameter is a variable declared in the function's parameter list. An argument is the value or expression supplied when calling the function.

#include <iostream>
using namespace std;

void greet(string name) {
    cout << "Hello, " << name << "!";
}

int main() {
    greet("Rahul");
    return 0;
}

Output

Hello, Rahul!

Here:

  • name is a parameter.

  • "Rahul" is the argument.

  • void means the function does not return a value.

This example also needs #include <string> to explicitly include the standard string type. A complete version is:

#include <iostream>
#include <string>
using namespace std;

void greet(string name) {
    cout << "Hello, " << name << "!";
}

int main() {
    greet("Rahul");
    return 0;
}

Example: Multiple parameters

#include <iostream>
using namespace std;

int subtract(int a, int b) {
    return a - b;
}

int main() {
    cout << subtract(15, 6);
    return 0;
}

Output

9

The order of arguments matters: subtract(15, 6) is not the same as subtract(6, 15).

5. Functions with no parameters

A function does not always need input parameters.

#include <iostream>
using namespace std;

void showMessage() {
    cout << "Welcome to Param Classes!";
}

int main() {
    showMessage();
    return 0;
}

Output

Welcome to Param Classes!

The empty parentheses in showMessage() indicate that the function takes no parameters.

6. void functions vs value-returning functions

There are two common categories of functions.

A. void function

A void function performs an operation but does not return a value to its caller.

void printLine() {
    cout << "----------";
}

Call it like this:

printLine();

B. Value-returning function

A value-returning function produces a result of its declared return type.

int square(int n) {
    return n * n;
}

Use its result like this:

int result = square(5);
// result is 25

Practical example: Print a result or return it?

#include <iostream>
using namespace std;

void printSquare(int n) {
    cout << n * n << endl;
}

int square(int n) {
    return n * n;
}

int main() {
    printSquare(4);

    int result = square(5);
    cout << result;

    return 0;
}

Output

16
25

Use a void function when the main task is an action, such as printing a message. Use a value-returning function when the result needs to be stored, compared, reused, or passed to another function.

7. Understanding the return statement

The return statement ends the current function and, for a non-void function, provides a value to the caller.

Example 1: Return a value

int doubleNumber(int n) {
    return n * 2;
}

Calling doubleNumber(6) produces 12.

Example 2: Early return

#include <iostream>
using namespace std;

bool isPositive(int n) {
    if (n <= 0) {
        return false;
    }

    return true;
}

int main() {
    cout << boolalpha;
    cout << isPositive(5) << endl;
    cout << isPositive(-2);

    return 0;
}

Output

true
false

The first return ends the function immediately if n is zero or negative. Otherwise, execution reaches return true.

Important rules

  • A non-void function should return a value compatible with its declared return type on every path that returns to the caller.

  • A void function may use return; to exit early, but it cannot return a value.

  • Code after a return statement in the same execution path will not run.

  • return is different from cout: printing displays text, while returning sends a result back to the caller.

8. Pass by value

By default, ordinary function parameters are passed by value. The function receives its own copy of the argument.

Changing that parameter does not change the caller's original variable.

#include <iostream>
using namespace std;

void changeValue(int x) {
    x = 100;
}

int main() {
    int number = 10;

    changeValue(number);

    cout << number;

    return 0;
}

Output

10

Although x becomes 100 inside the function, number remains 10.

Visual explanation

Caller variable

10

number

Copied parameter

10

x

Changing x changes the copy, not number in the caller.

Pass by value is useful when a function needs its own local copy or when working with small values such as integers and floating-point numbers.

9. Pass by reference

A reference parameter provides another name for the caller's existing variable. This lets the function modify the original value.

Syntax

void functionName(int &parameter) {
    // Parameter refers to the caller's variable
}

Example: Modify the original variable

#include <iostream>
using namespace std;

void changeValue(int &x) {
    x = 100;
}

int main() {
    int number = 10;

    changeValue(number);

    cout << number;

    return 0;
}

Output

100

The & in int &x makes x a reference to the caller's variable.

Example: Swap two numbers

#include <iostream>
using namespace std;

void swapNumbers(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 10;
    int y = 20;

    swapNumbers(x, y);

    cout << "x = " << x << endl;
    cout << "y = " << y;

    return 0;
}

Output

x = 20
y = 10

Because a and b refer to x and y, the swap changes the original variables.

Pass by value vs pass by reference

Feature

Pass by value

Pass by reference

Parameter

Local copy

Reference to caller's variable

Changes original variable?

No, not through the copy

Yes

Typical syntax

int x

int &x

Common use

Work with an independent value

Modify caller's value

Risk of side effects

Lower

Higher because the original may change

Important: References should be used intentionally. If a function needs to read a large object without copying it but must not modify it, a const reference is often appropriate:

void displayName(const string &name) {
    cout << name;
}

This avoids copying the string and prevents modification through the name reference.

10. Default arguments

A default argument is a value used when the caller omits a corresponding argument.

Example

#include <iostream>
using namespace std;

int add(int a, int b = 10) {
    return a + b;
}

int main() {
    cout << add(5) << endl;
    cout << add(5, 3);

    return 0;
}

Output

15
8

In the first call, b defaults to 10. In the second call, the supplied argument 3 is used instead.

Rules for default arguments

  • Default arguments are usually specified in the function declaration or definition visible at the call site.

  • Once a parameter has a default argument, parameters to its right must also have defaults.

  • You cannot omit an argument in the middle of a positional argument list.

For example:

int calculate(int a, int b = 5, int c = 10);

These calls are valid:

calculate(1);
calculate(1, 2);
calculate(1, 2, 3);

But you cannot use a normal function call to supply a and c while skipping only b.

11. Function overloading

Function overloading means defining multiple functions with the same name but different parameter lists.

This lets one function name support different kinds or numbers of inputs.

Example 1: Different numbers of parameters

#include <iostream>
using namespace std;

int add(int a, int b) {
    return a + b;
}

int add(int a, int b, int c) {
    return a + b + c;
}

int main() {
    cout << add(2, 3) << endl;
    cout << add(2, 3, 4);

    return 0;
}

Output

5
9

The compiler selects the appropriate overload based on the arguments.

Example 2: Different parameter types

#include <iostream>
using namespace std;

int multiply(int a, int b) {
    return a * b;
}

double multiply(double a, double b) {
    return a * b;
}

int main() {
    cout << multiply(3, 4) << endl;
    cout << multiply(2.5, 4.0);

    return 0;
}

Output

12
10

Important overloading rule

You cannot overload a function based only on its return type.

These two declarations cannot form separate overloads by themselves:

int getValue();
double getValue(); // Not a valid overload of the same signature

The parameter lists must differ in a way that produces a distinct overload. The return type alone does not distinguish them.

12. Local variables and scope

Scope determines where a variable can be accessed in a program.

A variable declared inside a function is generally a local variable and cannot be accessed directly from another function.

Example

#include <iostream>
using namespace std;

void showNumber() {
    int number = 50;
    cout << number << endl;
}

int main() {
    showNumber();

    // cout << number; // Error: number is not in this scope

    return 0;
}

Output

50

The variable number belongs to showNumber(). Its name is not directly available inside main().

Local variables in different functions

void first() {
    int value = 10;
}

void second() {
    int value = 20;
}

Both functions can have a local variable named value. These are separate variables with different scopes.

Best practice: Pass data through parameters and return values rather than relying on global variables unnecessarily. This makes functions easier to understand, test, and reuse.

13. Recursion — a function calling itself

Recursion occurs when a function calls itself to solve a smaller version of the same problem.

A recursive function needs two essential parts:

  1. Base case: Stops the recursion.

  2. Recursive case: Calls the function again with a smaller or simpler input.

Example: Factorial using recursion

The factorial of a positive integer \(n\) is:

\[ n! = n \times (n-1) \times \cdots \times 1 \]

For example, \(5! = 5 \times 4 \times 3 \times 2 \times 1 = 120\).

#include <iostream>
using namespace std;

int factorial(int n) {
    if (n <= 1) {
        return 1;
    }

    return n * factorial(n - 1);
}

int main() {
    cout << factorial(5);

    return 0;
}

Output

120

How the recursive calls work

factorial(5) = 5 × factorial(4)

factorial(4) = 4 × factorial(3)

factorial(3) = 3 × factorial(2)

factorial(2) = 2 × factorial(1)

factorial(1) = 1 ← base case

When the base case returns 1, the pending multiplications are evaluated, producing 120.

Caution: Recursion uses call-stack space. Missing or unreachable base cases can cause unbounded recursion and eventually stack exhaustion. For simple repetitive calculations, a loop may be more efficient and easier to follow.

14. Practical project — Calculator using functions

Let's create a basic calculator using separate functions for addition, subtraction, multiplication, and division.

Complete code

#include <iostream>
using namespace std;

double add(double a, double b) {
    return a + b;
}

double subtract(double a, double b) {
    return a - b;
}

double multiply(double a, double b) {
    return a * b;
}

bool divide(double a, double b, double &result) {
    if (b == 0) {
        return false;
    }

    result = a / b;
    return true;
}

int main() {
    double a, b, result;
    char op;

    cout << "Enter expression (example: 10 + 5): ";
    cin >> a >> op >> b;

    switch (op) {
        case '+':
            result = add(a, b);
            cout << "Result = " << result;
            break;

        case '-':
            result = subtract(a, b);
            cout << "Result = " << result;
            break;

        case '*':
            result = multiply(a, b);
            cout << "Result = " << result;
            break;

        case '/':
            if (divide(a, b, result)) {
                cout << "Result = " << result;
            } else {
                cout << "Error: division by zero";
            }
            break;

        default:
            cout << "Invalid operator";
    }

    return 0;
}

Example runs

Enter expression (example: 10 + 5): 10 + 5
Result = 15
Enter expression (example: 10 + 5): 10 / 0
Error: division by zero

Why this design works

  • Each arithmetic operation has its own function.

  • main() manages input, operation selection, and output.

  • The division function returns a Boolean indicating success or failure.

  • The result is passed by reference so that the division function can write the computed value back to the caller.

  • Division by zero is handled explicitly.

This separation makes each operation easier to test and extend.

15. Common mistakes in functions

Mistake 1: Calling a function before it is declared

If a function's definition appears later, provide a declaration before the call site.

int square(int n); // Declaration

Mistake 2: Forgetting to return a result

A non-void function must provide an appropriate return value on every path that returns to its caller.

Mistake 3: Expecting pass by value to modify the original

void update(int x) changes only the copy. Use int &x if the function should modify the caller's variable.

Mistake 4: Overloading only by return type

Functions with identical parameter lists cannot be overloaded solely because one returns int and the other returns double.

Mistake 5: Creating infinite recursion

Make sure every recursive path eventually reaches a base case.

16. Hands-on exercises

Try writing each program yourself before reviewing the examples above.

Exercise 1 · Easy

Even or odd

Write a function isEven(int n) that returns true if the number is even and false otherwise.

Exercise 2 · Easy

Maximum of two numbers

Write a function that receives two integers and returns the larger one.

Exercise 3 · Easy

Temperature converter

Create a function that converts Celsius to Fahrenheit using the formula:

\[ F = \frac{9}{5}C + 32 \]

Exercise 4 · Intermediate

Swap two numbers

Write a function that swaps two integers using reference parameters.

Exercise 5 · Intermediate

Function overloading

Create overloaded area() functions for a square, a rectangle, and a circle. Choose parameter lists that distinguish the overloads.

Exercise 6 · Intermediate

Prime number checker

Write a function isPrime(int n) that returns whether a number is prime. Test values such as 2, 9, and 17.

Exercise 7 · Challenge

Recursive Fibonacci

Write a recursive function that returns the \(n\)-th Fibonacci number. Define your indexing convention and test the base cases. Consider why naive recursion becomes slow for large values of \(n\).

17. Interactive knowledge-check quiz

Select an answer for each question, then submit to check your understanding.

Functions quiz

0 / 8 answered

1. What is the main purpose of a function?

To make every variable global

To group reusable code for a task

To replace all loops

To stop a program automatically

2. What does a void function indicate?

It returns an integer

It has no body

It does not return a value

It cannot accept parameters

3. What is a function prototype?

A function call

A declaration describing a function's interface

A loop inside a function

A return value

4. What happens when an int parameter is passed by value?

The caller's variable always changes

A copy of the value is passed

The parameter becomes global

The function cannot read it

5. Which parameter allows a function to modify the caller's integer directly?

int x

const int x

int &x

void x

6. Can two functions be overloaded using only different return types?

Yes, always

Yes, if their names are long enough

No

Only if both are void

7. What is essential for a recursive function to terminate?

A global variable

A base case that is eventually reached

A default argument

Function overloading

8. What does a default argument do?

Changes the return type

Provides a value when an argument is omitted

Makes every parameter a reference

Calls the function automatically

Submit quiz

Answer all eight questions to submit.

18. Module 8 completion checklist

Your learning progress

0 / 7

I understand function declarations, definitions, and calls.

I can use parameters and return values.

I understand void functions and early returns.

I can explain pass by value and pass by reference.

I can use default arguments and function overloading.

I understand local scope and recursion.

I have attempted the calculator project, exercises, and quiz.

←
Post 8 of 13
→