Skip to content

C++ Functions

A function is a block of code that runs when it is called. It can take data as input (known as parameters) and generate output (know as return value).

Functions are used to create reusable and modular codes.

Declaration, Definition, and Execution

A C++ function consists of two parts:

  • Declaration: the function name, parameters if any, and return type
  • Definition: the body of function

To execute a function, invoke the name with () and provide parameters if required.

For example

func-say-hi.cpp
#include <iostream>

using namespace std;

void sayHi()
{ // declaration
    // the body of the function (definition)
    cout << "Hi" << endl;
}

int main()
{
    cout << "Hello, World!" << endl;

    sayHi();

    return 0;
}

We create a function called sayHi() which takes no parameters and returns nothing (void).

It's important to know that user-defined function needs to be declared before main(). Otherwise, an error will occur, as follow.

func-say-hi-error.cpp
#include <iostream>

using namespace std;

int main()
{
    cout << "Hello, World!" << endl;

    sayHi();

    return 0;
}

void sayHi()
{ // declaration
    // the body of the function (definition)
    cout << "Hi" << endl;
}
func-say-hi-error.cpp:9:5: error: use of undeclared identifier 'sayHi'
    sayHi();
    ^
1 error generated.

However, we can fix it by separating the declaration and the definition. Later we would see it's normal to use header files to declare functions and then implement those functions in separate cpp files.

func-say-hi-error-fix.cpp
#include <iostream>

using namespace std;

void sayHi();

int main()
{
    cout << "Hello, World!" << endl;

    sayHi();

    return 0;
}

void sayHi()
{ // declaration
    // the body of the function (definition)
    cout << "Hi" << endl;
}

Parameters

Data can be passed to functions as parameters. Parameters act as variables inside the function.

Parameters are specified after the function name, inside the pair of parentheses. We can specify as many parameters as we want, just separate them with a comma. And for each parameter, make sure we specify the data type.

For example

func-say-hi-by-person.cpp
#include <iostream>

using namespace std;

void sayHi(string name)
{ // declaration
    // the body of the function (definition)
    cout << name << " says Hi!" << endl;
}

int main()
{
    cout << "Hello, World!" << endl;

    sayHi("Jack");

    return 0;
}

In case we have more parameters

func-say-hi-by-person-multiple-times.cpp
#include <iostream>

using namespace std;

void sayHi(string name, int times)
{ // declaration
    // the body of the function (definition)
    for (int i = 0; i < times; i++)
    {
        cout << i + 1 << ": " << name << " says Hi!" << endl;
    }
}

int main()
{
    cout << "Hello, World!" << endl;

    sayHi("Jack", 5);

    return 0;
}

We can also use a default parameter value, by specifying the value after =.

func-say-hi-by-person-multiple-times-default.cpp
#include <iostream>

using namespace std;

void sayHi(string name, int times = 10)
{ // declaration
    // the body of the function (definition)
    for (int i = 0; i < times; i++)
    {
        cout << i + 1 << ": " << name << " says Hi!" << endl;
    }
}

int main()
{
    cout << "Hello, World!" << endl;

    sayHi("Jack", 5);

    cout << endl;

    sayHi("Jill");

    return 0;
}

Return Value

The example functions above use the void as return value, indicating not to expect a return value. If a function shall return a value, specify the data type in declaration and use the return keyword in the definition of a function.

For example

func-add.cpp
#include <iostream>

using namespace std;

int add(int a, int b)
{ // declaration
    // the body of the function (definition)
    return a + b;
}

int main()
{
    int a, b;
    cin >> a >> b;

    cout << add(a, b) << endl;

    return 0;
}

Function Overloading

With function overloading, multiple functions can have the same name with different parameters.

For example

func-add-overloading.cpp
#include <iostream>

using namespace std;

int add(int a, int b)
{ // declaration
    // the body of the function (definition)
    return a + b;
}

float add(float a, float b)
{ // declaration
    // the body of the function (definition)
    return a + b;
}

float add(float a, float b, float c, float d)
{ // declaration
    // the body of the function (definition)
    return add(add(a, b), add(c, d));
}

int main()
{
    int a, b;
    cin >> a >> b;

    cout << add(a, b) << endl;

    float c, d;
    cin >> c >> d;

    cout << add(c, d) << endl;

    float e, f, g, h;
    cin >> e >> f >> g >> h;

    cout << add(e, f, g, h) << endl;

    return 0;
}

Pass by Reference

Normally data passed by parameters are used as values in a function, meaning that it does not change the original value if you apply some logic within a function.

Let's rewrite the add() function such that the parameters increment themselves before being added.

func-by-value.cpp
#include <iostream>

using namespace std;

int add(int a, int b)
{ // declaration
    // the body of the function (definition)
    a += 1;
    b += 1;
    return a + b;
}

int main()
{
    int a, b;
    cin >> a >> b;

    cout << "before add(): " << a << " " << b << endl;
    cout << add(a, b) << endl;
    cout << "after  add(): " << a << " " << b << endl;

    return 0;
}

However, when we use & in the parameter, the parameter would pass as reference, meaning that the logic applied in the function would modify the original value.

For example

func-by-reference.cpp
#include <iostream>

using namespace std;

int add(int &a, int &b)
{ // declaration
    // the body of the function (definition)
    a += 1;
    b += 1;
    return a + b;
}

int main()
{
    int a, b;
    cin >> a >> b;

    cout << "before add(): " << a << " " << b << endl;
    cout << add(a, b) << endl;
    cout << "after  add(): " << a << " " << b << endl;

    return 0;
}

Array as parameter

By the way, we can also specify a parameter to be an array.

For example

func-add-array.cpp
#include <iostream>

using namespace std;

int add(int values[10])
{ // declaration
    // the body of the function (definition)
    int sum = 0;
    for (int i = 0; i < 10; i++)
    {
        sum += values[i];
    }
    return sum;
}

int main()
{
    int numbers[10];
    for (int i = 0; i < 10; i++)
    {
        cin >> numbers[i];
    }

    cout << add(numbers) << endl;

    return 0;
}

Recursion

Recursion

Recursion is the technique of making a function call itself. (The example in overloading is actually not recursion. Why?) This technique provides a way to break complicated problems down into simple problems which are easier to solve.

For example, Fibonacci sequence

0 1 1 2 3 5 8 13 ...

can be defined in a recursive way, say Fib(n), such that

Fib(0)=0
Fib(1)=1

For all integers n, where n > 1

Fib(n) = Fib(n-1) + Fib(n-2)

Let's implement it in C++.

func-fib.cpp
#include <iostream>

using namespace std;

int fib(int n)
{ // declaration
    // the body of the function (definition)
    if (n == 0)
    {
        return 0;
    }
    else if (n == 1)
    {
        return 1;
    }
    else
    {
        return fib(n - 1) + fib(n - 2);
    }
}

int main()
{
    int n;
    cin >> n;

    cout << fib(n) << endl;

    return 0;
}

Assignment 17

Kattis Probelm / Bus