C++ Builder Tutorials

Functions in C++

A function is a task you are asking C++ to perform.

There are two kinds of functions: those supplied to you and those that you write yourself.

The functions that are supplied to you are usually in three categories:

  • functions built-in the Windows operating system
  • functions that are part of the C++ language
  • functions written by Embarcadero (included in the various libraries that are installed with the IDE).

Here we will be dealing with functions that you write.


A C++ function consists of a function header and a function body:

       ReturnType   FunctionName( Parameters )   { Body } 

Here are the parts of a function:

  • Return-type: a function can return a value. The return-type is the data type that value.
    The return value can be any of data type, such as a char, an int, a float, a double, a bool, a String, etc. For example, a function for calculating the area of a rectangle would return a numeric value.

    Some functions don't return a value. In this case, for the return-type use the keyword void.
  • Function name: the actual name of the function.
  • Parameters: a parameter is a placeholder. When a function is called, you pass values to the parameters. These values are referred to as arguments.
    The parameters list contains the type and name of every parameter.
    Parameters are optional; that is, a function may contain no parameters. In that case, leave the parentheses empty. But surely don't omit the parentheses themselves!
  • Function body: a collection of statements that define what the function does.

Function declaration

In order to create and use a custom function, you must firstly declare it. The syntax is:

ReturnType FunctionName(Parameters);

Example:

float AreaRectangle(float W, float L);


Function definition

To let the application know what a function is meant to do, you have to define it, describe its behavior.
The syntax:

ReturnType FunctionName()
{
body
}


Here is an example:

float AreaRectangle(float W, float L)
{
  return W * L;
}


Where to declare and define a function?

Functions cannot be called before they are declared. But a function can be declared before its definition.

If you use a function in one unit only, it's best to declare it before the main function(s) of the unit. You define it anywhere after the main function(s) of the unit. Example:

bool Odd(int x);
bool Even(int x);
//----------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
{
}
//----------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  int a = 3;
  int b = 4;
  if (Odd(a + b))
    ShowMessage("Odd");
  else
    ShowMessage("Even");
}

// Custom functions
//-----------------------------------------
bool Odd(int x)
{
  bool Result;
  Result = ((x % 2) != 0);
  return Result;
}

bool Even(int x)
{
  bool Result;
  Result = ((x % 2) == 0);
  return Result;
}

Declaring functions before they are defined is useful to reorganize the order of functions within the code.
Or sometimes, at least one of two function declarations is required, because they both contain a call to the other function, and there is no way to structure the code so that one function is defined before the other and vice versa.

If you have functions that you use in several units, all over the project, it's best to put them in a separate unit (see: a function library). In that case, the declarations are done in a "header" file, and the definitions in the "cpp" file.


Calling a function

Arguments can be passed to a function by value or by reference.

By default, arguments are passed by value. What is passed to the function are the values of these arguments at the moment of the call, which are copied into the variables represented by the function parameters. For example:

float x = 5.5;
float y = 3;
float z;
z = AreaRectangle(x, y);


In this case, the function is passed 5.5 and 3, which are copies of the original values of x and y. These values are used to initialize the parameters in the function's definition. Any modification of these variables within the function has no effect on the values of the variables x and y outside it.

In certain cases, though, it may be useful to modify an external variable from within a function. To do that, the arguments are passed by reference, instead of by value.

When a variable is passed by reference, what is passed is no longer a copy, but the variable itself! Modifications within the function body are reflected in the variables that were passed as arguments.

References are indicated with an ampersand (&).
Consider the following function definition:

int Plus3(int &x, int &y, int &z)
{
  x = x + 3;
  y = y + 3;
  z = z + 3;
  return (x + y + z);


Calling the function Plus3:

int n;
int i = 1, j = 2, k = 3;
n = Plus3(&i, &j, &k); // returns 15
// from this point on, i will contain 4, j contains 5 and k contains 6 !


Default values in parameters

Functions can also have optional parameters, for which no arguments are required in the call. For example, a function with three parameters might be called with only two. For this, the function must include a default value for its last parameter, which is used by the function when called with fewer arguments.
Note that the optional parameter(s) must be the last in the list.

For example:

int PlusPlus(int x, int y, int z = 2)
{
  int Result;
  Result = x + y + z;
  return Result;
}


Calling the function:

int a, b;
a = PlusPlus(1, 2, 3); // returns 6
b = PlusPlus(1, 2);    // returns 5


Recursivity

Some functions may be called by themselves. It is useful for some tasks, such as sorting elements, or calculating the factorial of numbers. For example, in order to obtain the factorial of a number (n!) the mathematical formula is:

n! = n * (n-1) * (n-2) * (n-3) ... * 1
Thus, 5! (factorial of 5) would be:
5! = 5 * 4 * 3 * 2 * 1 = 120

A recursive function to calculate this in C++ could be:

int Factorial(int i)
{
  if (i > 1)
   return (i * Factorial(i - 1));
  else
   return 1;
}


Calling the function:

int n;
n = Factorial(9); // gives 362880


Notice how we let function Factorial call itself, but only if the argument passed was greater than 1. Otherwise, the function would stay stuck in a loop, and once it arrived to 0, it would continue multiplying by all the negative numbers (certainly provoking an overflow error during runtime).


See also:

  A unit with functions