We have learned to write function prototypes using various examples. In this lesson, we will focus on learning how to implement the functions, that is what to write inside functions and the exact flow of how each function works as a module to solve the bigger problem.

Functions in C++

The general syntax for writing a function is the following:

returnType functionName(parameterType1 pName1, parameterType2 pName2, ...)
{
    // Write the function's implementation code here.
}

When defining a function, we write the function’s return data type followed by the function’s name and the input parameters inside the brackets (). The function implementation is written inside the curly brackets {}.

Remember, there are a few rules we need to follow when writing functions in our C++ program. If we write some function (let’s call it inner() for explanation’s sake) and we want to call it inside a specific function (let’s call it outer()), then we have the following:

  • Our function that we want to call (inner) needs to be defined before the outer() function as follows:

    // function definition
    int inner(int firstNum, int secNum)
    {
      // function's implementation code
    }
    int outer()
    {
      // calling the inner() function inside the outer() function
      inner(12, 40);    
    }  
    
  • Alternatively, at least its prototype (function declaration) has to be written before the outer() function. Only then can we write our function’s definition below the outer() function.

    // function declaration/prototype
    int inner(int firstNum, int secNum);
    
    int outer()
    {
      // calling the inner() function inside the outer() function
      inner(12, 40);
    }  
    // function definition
    int inner(int firstNum, int secNum)
    {
      // function's implementation code
    } 
    

    If we try to use the function without writing its prototype first, the compiler will give an error that the function is undefined. This is because the compiler needs to know that the arguments list (the values passed in curly brackets while calling) of the function being called matches the required parameters of the called function.

So without further ado, let’s start learning to implement functions using some examples!

Example 1: Area of a triangle

Now let us see an example of a function that calculates the area of a triangle.

We’ll take the base and height from the user and calculate the triangle area. Usually, we write a main() in which we do the following:

  1. Create the memory (variables to take input from the user).
  2. Take the user’s required inputs (the base and the height).
  3. Calculate the area of the triangle.
  4. Display the area.

We want to do step 3 only for the time being in a separate function so that whenever we need to calculate the triangle area, we may call this function.

Here is the implementation:

#include <iostream>
using namespace std;

// prototype of function TriangleArea
float triangleArea(int base, int height); 

int main()
{
    int b, h;
    cout << "Base of the triangle: " ;
    cin >> b;
    cout << "Height of the triangle: " ;
    cin >> h;
                // function being called
    float area = triangleArea(b, h);
    cout << "Area: " << area << endl;

    return 0;
}
// function definition
float triangleArea(int base, int height)  
{
    return ((base * height)/2);
}




Calculating the area of a triangle

Now do the following:

  • Comment the line 5 and run the code. You will see a syntax error that the triangleArea() was not declared in this scope.

  • Uncomment back the line 5 and run the code and, as input, enter 5 and 6 as the base and height respectively. Execute the code step-by-step in the debugger and see how the function is called from line 15 and how the return instruction brings back the calculated area.

  • Try with 2 or 3 more inputs, where at least one value (base or height) must be an even number.


There is a logical error in the code above. Try running the code above using inputs 7 and 5 as the base and height and see what that error is.

Did you see the problem?

The code should return 17.5. Instead, it returns 17. Although the return type of triangleArea() is float, it still does not return the decimal part of the result. The reason is that integer arithmetics yields integers as the answer, even if you store the result in double/float data types.

Let’s try and solve a quiz question below to see its possible fix.

Q

(Select all that apply.) Which of the following return statements would fix the logical error below?

float traingleArea(int base, int height)
{
   // return statement
}
A)

return ((base*height)/2.0);

B)

return (1.0 * (base*height/2));

C)

return ((base*height*1.0)/2);

Instruction: Fix the error in the above example by replacing the division by 2 with 2.0 and run the code again.

    return ((base * height)/2.0);

Example 2: Surface area and volume of a cuboid

In this example, we would like to write a program that takes input (the dimensions of the cuboid, that is its length, breadth, and height) from the user and calculates the surface area and volume of the given cuboid.

In this program, we will write four helping functions, rectangleArea(), surfaceArea(), volumeOfCuboid(), and printResult(). Each function will do the following required task:

  • rectangleArea(): This should take the length and width as parameters and return the area of the rectangle.

  • surfaceArea(): This should take the length, breadth, and height of the cuboid and return the surface area of the cuboid, by calling rectangleArea() three times at least (for the area computation of each face).

  • volumeOfCuboid(): This should take the length, breadth, and height of the cuboid and return its volume.

  • printResult(): This should take the surface area and volume of the cuboid, and display an appropriate message.

Write the program below in the playground and execute it step by step in the debugger.

#include <iostream>
using namespace std;

// Add prototype of functions
// int rectangleArea(int length, int breadth); 
// int surfaceArea(int length, int breadth, int height);
// int volumeOfCuboid(int length, int breadth, int height); 
// void printResult(int area, int volume);

int main()
{
    int length, breadth;  // Hint: any other variable needed?
    cout << "Length of the cube: " << endl;
    cin >> length;
    cout << "Breadth of the cube: " << endl;
    cin >> breadth;
    // Hint: any other variable input needed?

    // call functions here 

    return 0;
}
// add the implementation of rectangleArea and 
// surfaceArea and VolumeOfCuboid
Calculating the volume of a cube

Instruction: Below is the solution to the above problem. You may click the “Show Solution” button to view it and add the code in the above playground and test it. Please do not copy and paste the code (rather, write it by yourself).

One thing to note is that, along with the three functions rectangleArea(), surfaceAreaOfCuboid(), and volumeOfCube(), we created another function called printResult() to print the area and volume of the cuboid. We could have just used cout for printing in the main(), but we did not.

This is especially helpful to keep the computation and printing parts separated and integrated into one place within a program. We may also need these functions anywhere else separately, so making them modules will make it convenient for us to call them, rather than implement them all over again.

Another important point to note is that our function, printResult(int area, int volume), has the void return type. This is used when the function does not need to return anything. For example, we are only displaying the area and volume in the printResult(int area, int volume) function and not returning anything.

Usually, all the printing functions have the void return type.


Example 3: Calculator program using functions

Remember we created a calculator program in the previous chapter? Below is the main() function of our last program that we created using switch statements.

int main()
{
    int num1,num2,result;
    char operation;
    cin >>  num1 >> operation >> num2;

    switch(operation)
    {
    case '+': // case will save sum if input operation is +
        result=num1+num2;
        break;
    case '-': // case will save subtraction if input operation is -
        result=num1-num2;
        break;
    case '/': // case will save quotient if input operation is /
        result=num1/num2;
        break;
    case '%': // case will save remainder if input operation is %
        result=num1%num2;
        break;
    case '*': // case will save multiplication if the input symbol is *
        result=num1*num2;
        break;
    default: // default will be executed in case of wrong input
        cout << "invalid symbol." << endl;
    }
    cout<<result<<endl;
    return 0;
}

Let’s modify it by using functions for calculations instead! Can you think of why we may want to do this? We will ask you the reason again in a while; keep thinking about it in the background while reading the implementation.

We’ll start by making a calculator function with 3 parameters, (two integers and one character operator) like this:

// function prototype
int calculator(int num1, int num2, char symbol);

The implementation of the function would remain the same as our original program. Though we can change it (make separate functions for each operation), let’s just use the same code for now.

Look at the animation below:

Let’s use it in our code editor below:

#include <iostream>
using namespace std;

// function prototype
int calculator(int num1, int num2, char symbol);

int main()
{
    int num1,num2, answer;
    char operation;
    cout << "First operand: " << endl;
    cin >> num1;
    cout << "The operator: " << endl;
    cin >> operation;
    cout << "Second operand: " << endl;
    cin >> num2;
    
    answer = calculator(num1, num2, operation);
    cout << answer << endl;

    return 0;
}    

// function definition
int calculator(int num1, int num2, char operation)
{ 
    int result;
    switch(operation)
    {
    case '+': // case will save sum if input operation is +
        result=num1+num2;
        break;
    case '-': // case will save subtraction if input operation is -
        result=num1-num2;
        break;
    case '/': // case will save division if input operation is /
        result=num1/num2;
        break;
    case '%': // case will save mod if input operation is %
        result=num1%num2;
        break;
    case '*': // case will save multiplication if input operation is *
        result=num1*num2;
        break;
         
    default: // default will be execute in case of wrong input
        result = -1;
        cout << "invalid symbol." << endl;           
          /* 
            We are printing in value returning function which is 
            considered as an "extremely bad programming practice" 
            we will talk about this later.

            but for the time being let us move on.
          */
    }
    return result;
}    








Implementation of a Calculator() using a switch statement

Instruction: Execute the above program step by step in the debugger, and understand the flow of the program. We should observe the watches and understand the working of function calls and how the entire functional program executes.


There are a few important points to note about functions. The variables result, num1, num2, and operation in the calculator(int num1, int num2, char operation) function are local variables and cannot be accessed outside the function.

The local variables declared and used within a function call get created whenever the function is called and initialized with the values passed as arguments or assigned within that function. Remember, before returning to the location where the function was called, all the function’s local variables are destroyed.

Practicing with functions in C++

In the remaining lessons of this chapter, we will revisit some of the problems we covered previously. We’ll modify our programs using this function-oriented approach.

We will see how those programs will be transitioned so that each code can be reused multiple times without being rewritten! We will simply have to call each function (module) whenever we need to perform a specific task.