Home | API | MFC | C++ | C | Previous | Next

Programming With C++

Functions

A function is a unit of code grouped to perform a specific task. Functions provide a way to compartmentalise and organise a program. Functions are identified by a name and enclosed within scope brackets and may be terminated by a return statement. After a function call, the execution of the program branches to the first statement in that function and continues until it reaches a return statement or the last statement of the function. At that point, execution resumes at the place where the function was called. A function can have multiple parameters separated by commas, but it can have only one return type. A function that does not need to return a value is declared as void.  In C++, one function cannot be embedded within another function. Functions are denoted by the function name followed by the parentheses and preceded by the return type(if any).

Function Prototype

The function prototype declares a function prior to its definition and details its name, the list of parameters the function accepts, and the return type of the function. The compiler needs to know this information prior to the function being called. A function defined before main() (forward declaration) does not need a function prototype.

Function calls

A function call is an expression that passes control and arguments (if any) to a function. When a function declaration contains parameters, the function call needs to send arguments. Arguments are values the function requests within its parameter list.

Function Parameters

The purpose of parameters is to allow functions to receive arguments. Multiple parameters are separated by a comma. These parameters don’t have to be of the same data type. Any valid C++ expression can be a function parameter, including constants, logical expressions, objects, and other functions that return a value. Parameter data can be passed into and out of methods and functions by value or by reference.

Pass by Value - The data associated with the actual parameter is copied into a separate storage location assigned to the function parameter. Any modifications to the function parameter variable inside the called function or method affect only the local parameter.  The parameters passed to a function become local variables within that function, even if they have the same name as variables within the scope of the statement calling the function.

Pass by Reference - Using "pass by reference", the function parameter receives a reference or pointer to the variable in the calling environment. Any changes to the function parameter are reflected in the original calling environment variable.

Pass-by-references is more efficient than pass-by-value, because it does not copy the arguments.

The code selection below outline 3 different methods for passing data to a function

#include <iostream>
using namespace std;
void swapThemByVal(int, int);
void swapThemByRef(int& , int&);
void swapThemByPtr(int *, int *) ;
main()
{
int x = 10, y = 20;//declare and initialise variable values
swapThemByVal(x, y);//pass be value
cout << x<< " " << y << endl; // displays 10 20
swapThemByRef(x, y);//pass by reference
cout << x << " " << y << endl; // displays 20 10
swapThemByPtr(&x, &y);//pass by pointer
cout << x << " " << y << endl; // displays 20 10
return 0;
}
void swapThemByVal(int num1, int num2)
{
int temp = num1; num1 = num2;
num2 = temp;
}
void swapThemByRef(int &num1, int &num2)
{
int temp = num1; num1 = num2;
num2 = temp;
}
void swapThemByPtr(int *num1, int *num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}

Default Function Parameters

Normally when a function is declared in a prototype to receive one or more parameters, the function can only be called with parameters of that data type, however, if the function prototype declares a default value for a parameter the function can be called without that parameter.

Default arguments are only allowed in the parameter lists of function declarations. The default values can be overridden with a user-supplied value if required using the normal call syntax. When a function has more than one parameter, default values are assigned based on the order of the parameters. Any parameter can be assigned a default value, with one important restriction: If a parameter does not have a default value, no previous parameter may have a default value.

The following declaration is not permitted

long setvalues(int x, int y, int z = 1, int t) - note that x & y are before z

The correct declaration would be

long setvalues(int x, int y, int t,int z = 1);

Passing an Array of Values to a Function

C++ does not allow an entire array to be passed as an argument to a function. Pointers to an array are passed as an argument by specifying the array's name without an index. The argument represents the memory address of the first element of the array. Any changes made in the function will therefore be reflected in the original array. To pass a single-dimension array as an argument in a function use one of the following.

void myFunction(int *param) - array passed as pointer
void myFunction(int param[10])  - array passed a sized array
void myFunction(int param[]) - array passed as unsized array

All these variants are all functionally identical. Each effectively tells the compiler that an integer pointer is going to be received.

Returning Values from Functions

Functions can return a value or return nothing (void).To return a value from a function, the keyword return is followed by the value to return. A function’s return value is copied into a placeholder on the stack. The return value is popped off the stack and can be assigned as the value of the function. If the value of the function isn’t assigned to anything, no assignment takes place, and the value is lost. After a return statement, program execution continues immediately after the statement that called the function. A function can have multiple return statements

Auto-Typed Return Values

Another feature added with version C++14 is the automatic deduction of a function’s return type with the auto keyword. This tells the compiler to deduce the return type of the functions by deduction -

auto subtract(int x, int y)
{
return x — y;
}

Functions that rely on automatic return type deduction need to be defined before they’re invoked so the compiler knows a function’s return type at the place where it is used. If a function has multiple return statements, they need to all deduce to the same type.

Using Variables with Functions

Local Variables - A variable created in a function is called a local variable because it only exists within the scope of the function. When the function returns, all of its local variables go out of scope and cease to exist. Local variables are declared like any other variable. The parameters received by the function are also considered local variables. Local variables are stored in an area of memory called the stack.

Global Variables - In c++, variables defined outside of all functions, including the main() function are known as global variables and are visible everywhere in the program. Variables defined outside of any function have global scope and thus are available from any function in the program, including main().  Since Global variables can be changed in any part of the program this can lead to a problem in tracking down errors.  Limiting the scope of a variable to the particular section of a program limits the amount of checking that must be done in the event of an error. The use of global variables is not considered good programming practice. Non-constant global variables are stored in the "data" segment of memory

Overloading Functions

Functions with the same name and return type but with different parameters are called overloaded functions. Overloaded functions can be used in situations where the function called depends on the type of parameters specified in the function call. It is, therefore, possible to create a function that performs a task on different types of data without creating unique names for each function. For example - 

int proc(int);
int proc(int, int);
int proc(long, long);
int proc(cint);

The proc function above is overloaded with four different parameter lists. The second and third differ in the data types and the third and fourth differs in the number of parameters. The parameters the function is called with determine which function will be called. Overloaded functions don't have to have the same return type, but it is not possible to overload by return type.  Function overloading also is called function polymorphism.

Inline Functions

Since a function call results in some overhead, declaring a function as inline causes the contents of the function to be placed inline were its called. This substitution is carried out by the C++ compiler at compile time. Inline function will generally only increase efficiency if they are small. To make any function as inline, start its definitions with the keyword “inline".

The syntax for defining the function inline is:

inline return-type function-name(parameters)
{
// code

Recursion—Functions That Invoke Themselves

A function that calls itself is known as a recursive function. The recursion proceeds until some condition is met which breaks the recursive cycle. The following simple recursion function demonstrates how a countdown procedure calls itself until the exit condition is met.

#include <iostream>
void printFun(int countp)
{
if (countp < 1) //exit function if value of countp is smaller than 1
return;
else
{
printf("Count value = %.i \n", countp);
printFun(countp-1); //recursive function calls itself
return;
}
}
int main()
{
int count = 3;
printFun(count); //call recursive function
}

Home | API | MFC | C++ | C | Previous | Next
The Basics | Variables and Constants | Arrays | C-strings | Expressions and Operators | Controlling Program Flow | C++ Functions | Pointers and References | Memory Map and Free Store | Smart Pointers | Classes | Structures | Inheritance | Polymorphism | Templates | The Standard Template Library | The STL String Class | Namespace | Type Conversions | Input and Output Streams | The C++ Preprocessor | Exception Handling

Last Updated: 15 September 2022