7 minutes read

Functions are a fundamental concept in programming that allows you to encapsulate a block of code (some set of instructions that you or another programmer wrote) and execute it multiple times. They provide modularity, reusability, and improve the overall organization of your code. Now your code will move to a new level! In this topic, you will explore the key aspects of functions in C++.

Functions – what are they?

As you have seen before, the main() function serves as the entry point of a C++ program. It is where the execution begins and ends. Within the main() function, you can write a series of statements that define the logic and operations of your program.

If you wish, you can write the entire program within the main() function. For small programs, this is usually done. However, if your program exceeds 20-30 lines of code (this is a very approximate measure), it's essential to consider organizing the code. Doing so simplifies development, especially when working collaboratively, improves code readability, and eases testing, debugging, and error detection. To achieve this, functions are used.

Functions in C++ are named blocks of code that you can call and execute at any point in the program. They allow you to break down complex tasks into smaller, manageable units, making the code more modular and easier to understand. You can use functions to perform specific actions, calculate values, or provide abstractions for repetitive tasks.

Think of a function as a small factory or tool that performs a specific task at your request. It has a name, for example (let's invent a fictional function), "makeCake()", and it knows how to bake a cake. Instead of baking a cake manually every time, you can simply call the "makeCake()" function and get your cake ready.

Function composition

In C++, to work with functions, you need to follow several steps:

  • Define the function: Describe its composition. This is a mandatory step where you specify how your function will operate.

  • Call the function from your code (from the main function or another function). This is also a mandatory step since a function is like a "Chekhov's gun" (if you've created it, you should use it at least once).

  • Declare the function (provide its prototype). This is an optional step, but in some situations, it's crucial.

Next, let's examine each step in detail and put everything in its place.

The declaration, also known as the function prototype, provides information about the function's name, return type, and parameters, without specifying the implementation details. The function definition includes the actual implementation of the code block.

Here is the function declaration syntax:

return_type function_name(parameter_list);

return_type - This specifies the data type of the value that the function will return after performing its task. For example, if the function performs a calculation and returns an integer result, the return type would be int. If the function doesn't return anything, the return type is specified as void.

function_name - This is the name given to the function, which is used to call and identify the function when it is used in the program. It should be a meaningful name that reflects the purpose of the function. The rules for choosing a name are the same as for a variable.

parameter_list - This is a list of input parameters (or arguments) that the function receives when it is called. Each parameter is defined with its data type and name, separated by commas. These parameters allow the function to receive data from the calling code, which it can use for its computations.

As for any expression, do not forget about ";".

And here are some examples:

// the function does not take any parameters and does not return anything
void makeCake(); 

// takes two integers and returns an integer value
int sum(int one, int two); 

Why might you need it? Imagine you're working on a big program with numerous functions and extensive code. To manage complexity and keep things organized, you might divide your code into several files, which is a common practice.

However, this division can create a challenge for the compiler. What if that function is defined in a different file? The compiler won't automatically know about it. That's where declaration comes in. In the main file, usually known as the 'entry point,' you provide what's known as a declaration for each function you're going to use.

By doing this, you're helping the compiler build a roadmap of your program's structure.

Function definition

A function definition provides the actual implementation or body of a function. It defines the statements and actions that the function performs when called. A function definition consists of:

  • a return type

  • function name

  • parameter list

  • and the set of statements enclosed in curly braces.

The syntax for a function definition is as follows:

return_type function_name(parameter_list)
{
    // Statements
}

And here are some examples:

int sum(int a, int b) {
    int result = a + b; // function returns int
    return result; // exit from function and return the result
}

Notice there is no ";" after the closing brace, like structures.

Call and use

And the final part of our story... function invocation.

Function invocation is an expression that instructs the processor to execute the function at that point, following these steps (conceptually):

  1. Pause the execution of the current function and start executing another function. In the example below, the current function is main() and the other function is sum().

  2. The processor creates a "bookmark" at the current execution point and then executes the invoked function.

  3. Once the invoked function completes execution, the processor returns to the "bookmark" and resumes execution of the interrupted function.

The function from which the call originates is referred to as the caller (main()), while the function being called is the callee (sum()), for example:

#include <iostream>

int sum(int a, int b) { //function definition (nothing happens before calls)
    int result = a + b; 
    return result; 
}
 
int main()
{
    // stop the execution of the main() function
    // call the sum function and pass it two numbers (3 and 4)
    // wait for sum to complete
    // after completion, enter the amount into the result variable
    int result = sum(3, 4); 
    std::cout << "The sum of 3 and 4 is: " << result << std::endl;
 
    result = sum(1, 3); 
    std::cout << "The sum of 1 and 3 is: " << result << std::endl;

    result = sum(result, result); 
    std::cout << "The sum is: " << result << std::endl;

    // You can even do this,  
    // but you need to remember about the readability of the code		
    result = sum(sum(1,2), sum(3,4)); 
    std::cout << "The sum is: " << result << std::endl;

    return 0;
}
 

The result of running this code:

The sum of 3 and 4 is: 7
The sum of 1 and 3 is: 4
The sum is: 8
The sum is: 10

Have you been paying close attention to the code? If yes, I'm sure you've noticed another fantastic and useful feature of functions, namely, local scope. You've created variables with the same name, result, both in the main() function and the sum() function. However, these are completely separate variables, and this is possible because a function is like its own little world, with a single entrance (function parameters) and a single exit (return value). "What happens in Vegas, stays in Vegas," as they say.

Time tested tips

While learning the C++ language, you'll have to write numerous programs that typically consist of three main global parts:

  • Obtaining data from the user.

  • Processing the data.

  • Displaying the result.

Of course, you are the creator of your programs, especially in C++ (no one will stop you from shooting yourself in the foot), but eventually, through mistakes and pain, you will likely arrive at this realization on your own. So why waste time? Just incorporate these principles right from the beginning.

One of the most common challenges that beginners face is understanding where, when, and how to effectively use functions. Here are several key recommendations for writing functions:

  1. Code that appears more than once in a program is better rewritten as a function. For example, if you're obtaining data from the user multiple times in the same way, it's an excellent opportunity to create a separate function.

  2. Code used for sorting anything is better suited for a separate function. For instance, if you have a list of items to be sorted, you write a sorting function that takes in the data and returns an ordered list.

  3. A function should perform one (and only one) task.

  4. When a function becomes too large, complex, or unclear, divide it into smaller parts (smaller functions). This is called code refactoring.

Benefits of using functions

I believe you have already seen the importance of functions and their various advantages, making them extremely valuable in complex programs. Here are a few more points in favor of using functions:

  • Structure: As programs grow in size and complexity, keeping all the code inside main() becomes challenging. You can write a function as a mini-program separate from the main program, without worrying about the rest of the code. This allows you to break down complex tasks into smaller and simpler ones, significantly reducing the overall program complexity.

  • Reusability: You can call a function multiple times once you've defined it. This helps avoid duplicating code and minimizes the chances of errors when copying/pasting code. You can also use functions in other programs, which reduces the amount of code you need to write from scratch each time.

  • Testing: Since functions remove redundant code, testing becomes easier. As functions are self-contained units, you only need to test them once to ensure their functionality. After that, you can reuse them multiple times without the need for retesting (unless you make changes to that function).

  • Upgradability: When you need to change a program or extend its functionality, functions are an excellent option. You can make changes in one place and have them work everywhere using functions.

  • Abstraction: To use a function, you only need to know its name, input data, output data, and where it's located. You don't need to know how it works. This is very useful for writing code that is understandable to others (for example, the C++ Standard Library and everything within it are designed with this principle in mind).

Conclusion

Functions play a crucial role in C++ programming by allowing us to break down complex tasks into smaller, manageable units. They are fundamental building blocks for creating robust and scalable applications.

Understanding and using functions in C++, you can create programs of absolutely any complexity, and this is not an exaggeration!

16 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo