Functions in C++

Functions are a way of grouping sets of commands so that they may be easily reused in different parts of a program.

For instance, if there were twelve different places in a program where you needed to compute square roots, it would be extremely inconvenient to have to rewrite essentially the same code sequence in all twelve places. Furthermore, if you needed to alter your square root computations, it might require alterations in all twelve locations - leading to an increased chance of confusion and errors.

A function takes a block of code and gives it a name, as well as giving names to the different kinds of data (parameters) it needs to process. When you want to use a function in a program you simply specify the name of the function and the data you want to supply to it:

// Here we assume there is a function named SquareRoot, that takes
// a floating point value as a parameter and returns a floating
// point value (the square root of the parameter it was given)
x = SquareRoot(36.0);  
There are already a collection of functions available for you to use (library functions) and later we will also consider the ways in which you can create your own functions.

Library functions

Math libraries

Function parameters

Function examples

Creating your own functions

Functions as part of top-down design

Declaring your functions

There are three parts to a function declaration:
// printdata prints out the passed parameters
// it does not return any value
void  printdata(int x, char y);

// getcommand needs no parameters, 
// it gets a single character command from the user 
// and returns this to the calling routine
char  getcommand();

// calculate area calculates and returns a rectangle's area 
// given the height and width parameters
float calculate_area(float width, float height);

Implementing your functions

The basic layout of a function implementation is as follows:
<return type> <function name> ( <list of formal parameters> )
{
    // local variables,
    // executable statements,
    // return statement if return type not void
}
Examples:
void printdata(int x, char y)
{
   printf( "The integer field has value %d", x);
   printf( ", while the character field is %c\n", y);
}

char getcommand()
{
   char cmd;
   printf( "Please enter a single letter command\n");
   scanf("%c", &cmd);
   return(cmd);
}

float calculate_area(float width, float height)
{
   return(width * height);
}

Functions example

Suppose our problem is as follows: we want to calculate how much paint is needed to paint a particular wall, and how much that is going to cost.

Design

  1. Get wall area from user
    1. Prompt user for wall dimensions (height, width in metres)
    2. Read in wall dimensions
    3. Return area = height * width
  2. Get cost of paint (per litre) from user
    1. Prompt user, read in and return result
  3. Get area of paint coverage (sq. metres per litre) from user
    1. Prompt user, read in and return result
  4. Calculate amount of paint needed
    1. Exact amount of paint needed = area / coverage per litre
    2. Round up exact amount to nearest whole number
  5. Calculate cost of paint
    1. Cost = number of litres needed * cost per litre
  6. Display information
    1. Print the room area, coverage of paint, and cost of paint per litre
    2. Print number of litres needed, and corresponding cost

Implementation

#include <cstdio>
#include <cmath>

float Get_wall_area();

float Get_paint_cost();

float Get_paint_coverage();

int Calculate_paint(float area, float coverage);

float Calculate_cost(int litres_paint, float unit_cost);

void Display_results(float area, float coverage, 
      float unit_cost, int litres_paint, float total_cost);

int main()
{
   float area, coverage, unit_cost, total_cost;
   int litres_paint;

   area = Get_wall_area();
   unit_cost = Get_paint_cost();
   coverage = Get_paint_coverage();
   litres_paint = Calculate_paint(area, coverage);
   total_cost = Calculate_cost(litres_paint, unit_cost);
   Display_results(area, coverage, unit_cost, 
                                litres_paint, total_cost);
}

float Get_wall_area()
{
    float height, width;
    printf( "Please enter the room height and width ");
    printf( "in metres, then enter return\n"); 
    scanf("%f", &height);
    scanf("%f", &width);
    return(height * width);
}

float Get_paint_cost()
{
   float cost;
   printf( "Please enter the paint cost per litre");
   scanf("%f", &cost);
   return(cost);
}

float Get_paint_coverage()
{
   float coverage;
   printf( "Please enter the number of square metres");
   printf( " of wall space that can be covered with ");
   printf( "a single litre of paint\n");
   scanf("%f", &coverage);
   return(coverage);
}

int Calculate_paint(float area, float coverage)
{
    return( int( ceil(area / coverage)));
}

float Calculate_cost(int litres_paint, float unit_cost)
{
    return( litres_paint * unit_cost );
}

void Display_results(float area, float coverage, 
     float unit_cost, int litres_paint, float total_cost)
{
    printf( "For a wall with area %f", area);
    printf( " square metres, we require ");
    printf( "%f litres of paint\n", litres_paint);
    printf( "costing %.2f", unit_cost);
    printf( " dollars per litre,\n");
    printf( "gives a total cost of $%f\n", total_cost);
}

Formal vs actual parameters

Functions without parameters

Value parameters: passing information

Reference parameters: functions with side effects

A function can only actually return one value. Suppose we want a single function to compute several values for us, how do we access them? Reference parameters allow the function to access and change the values of variables passed as parameters. We specify reference parameters using the & symbol.
void swap(int &x, int &y);

int main()
{
   int var1 = 13;
   int var2 = -5;
   swap(var1, var2);
   print("%d %d\n", var1, var2);
}

void swap(int &x, int &y)
{
   int temp;
   temp = x;
   x = y;
   y = temp;
}
Inside swap, x is acting like another name for var1, while y is acting like another name for var2.

Parameter passing examples

#include <cstdio>

double get_area_height_width(float &height, float &width);

int main()
{
   float wallheight, wallwidth, wallarea;
   wallarea = get_area_height_width(wallheight, wallwidth)
   printf( "area %f = ", wallarea);
   printf( "width %f * ", wallwidth);
   printf( "height %f\n", wallheight);
}

double get_area_height_width(float &height, float &width)
// set width and height to user input values
// and return area = height * width
{
    printf( "Please enter the wall height\n");
    scanf("%f", &height);
    printf( "Please enter the wall width\n");
    scanf("%f", &width);
    return(width * height);
}
Because of the & symbols, height and width are local names for wallheight and wallwidth, whose values can really be changed. If the & symbol is left off, get_area_height_width would only receive copies of the values of wallwidth and wallarea, and would not be able to change the values of the `real' variables.

Reference parameters: restrictions

Only variables can be passed to reference parameters, and they must have the exact same data type as the reference parameter
double myfunction(int &refparam);

int main()
{
   double x;
   int y;

   x = myfunction(3);  // illegal, 3 is not an integer variable
   x = myfunction(y);  // is o.k.
}
The reason for this is that when a parameter is declared as a reference parameter, the function can make assignments to the parameter,
   // could appear inside myfunction
   refparam = 17;
In the first example above this would mean 3 = 17; which makes no sense whatsoever

Parameter default values

When creating prototypes for our functions, we can assign default values for the parameters, e.g.
// get the user to enter an integer in the range min..max
int getInteger(int min=0, int max=100);
If the function is called normally, i.e. with two parameters, then min and max have the values the caller passed.

However, if the function is called without parameters then it uses the default values supplied in the prototype.

For example, x = getInteger(3,10); would use 3 for min and 10 for max, but x = getInteger(); would use 0 for min and 100 for max.

If the function is called with only some of the optional parameters then it assumes the parameters at the end of the list are the ones that use default values. For example, the call x = getInteger(5); would use 5 for min and 100 for max.

Note that the default values are only placed in the prototype - if you place them in both the prototype and the full function implementation you will get a compile-time error.