User-defined Functions

User-defined functions are the fundamental unit to organize code in C++ programming language.

Purpose

  • Readability, maintainability

    • Shorter function body

    • Unique name for a code block

  • Code reuse, write once, use many times

  • Affect the outside world

    • Return a value

    • Modify reference or pointer-typed parameters

    • Input/output

    • Modify global variables (AVOID!)

Declaration

  • Optional but strongly recommended

  • Declarations in header file enables function reuse in another cpp file

  • May omit parameter names

  • May provide default value for parameters

  • Public function declarations

    • Functions to be used by other cpp files

    • In the header files

    • Add documentation

  • Private function declarations

    • Functions to be used only in the current cpp file only

    • In the cpp files

  • Return type

    • a concrete type: expecting a value of the specified type

    • void: not expecting anything

Definition (implementation)

  • In the cpp files

  • Formal parameters

    • Parameters listed in the parenthesis

    • Must have types and names specified

    • May provide default value for parameters

    • Stored the same way as local variables

  • Must align to declarations

  • Return statement

    • may have multiple in a same function definition

    • returns a value as a copy (by-value) to the caller (except in void functions)

Default value

  • Provide starting from last to the first parameter

  • Must only appear once, either in declaration or definition

  • Default value in declarations is recommended

Function call

  • Functions must be either declared or defined before being called

  • Actual parameters

    • Values provided in function calls

    • Rvalues in the parenthesis

    • Never add types

  • Usages

    • as a statement strcpy(str1, str2);

    • as part of an expression (non-void functions) cout << sqrt(4) << endl;

Function Pitfalls

  • Declaration/definition after call

  • Default values both in declaration and definition of a same function

  • No parameter name in definition

  • Type of parameter provided in function call

 1// ==== functions ====
 2
 3// ---- bad default values ----
 4
 5// v1 cannot have default value if v2 do not have
 6void func1(int v1 = 10, int v2);
 7
 8// both have default value
 9void func1(int v1 = 10);
10void funct(int v1 = 10) { ... }
11
12// ---- wrong definitions ----
13void func1(int) { ... }
14
15// ---- wrong function calls ----
16func1(int a);

Parameter Passing

  • parameter passing is the same as initialization (not assignment!)

    • type conversion will happen as needed

  • Pass by value

    • The default method to pass parameters

    • The value of the actual parameter is used to initialize the formal parameter

    • A copy is created like in a normal initialization

  • Pass by pointer

    • A memory address is passed by value

  • Passing arrays

  • Pass by reference

Scope

  • Definition: The life span of an entity (variable, function, type, etc.)

  • local scope to a function: local variables and formal parameters

    • NEVER return a local variable by reference or pointer!

    • NEVER return a local array (only pointer will be passed out, the array content will not)! Return a dynamic array instead.

  • Code block based scope

     1// example 1, out-of-scope access
     2// for loop is a block even without {}
     3for (int i = 0; i < size; ++i)
     4  cout << i << endl;
     5cout << i << endl;  // will fail because i is not declared here
     6
     7// example 2, shadowed name
     8int i = 100;
     9{
    10  int i = 10;  // treated as another variable, valid in this block only
    11  cout << i << endl;  // get 10, outside i is shadowed
    12}
    13cout << i << endl;  // get 100
    14
    15// returning an dynamic array
    16// should be deleted after use
    17int *makeArray(int size) {
    18  return new int[size];
    19}
    20
    21// ---- Wrong ----
    22// returning local array
    23int *makeArray(int size) {
    24  int array[size];
    25  return array;
    26}
    27
    28// ---- Wrong ----
    29// returning local variable by reference/pointer
    30string *func() {
    31  string str = "abc";
    32  return &str;  // memory address is passed out, str will be destroyed
    33}
    

Overloading

Same name but different parameters (type, order, number) so the function call can match the correct function. Because the return type and formal parameter names does not affect the function call, differences in return type and formal parameter names will not be valid overloading.

 1// ==== Function Overloading ====
 2
 3// given this function
 4int func1(int name);  // func1(3);
 5
 6// ---- Correct ----
 7int func1(double);  // func1(3.0);
 8int func1(int, int);  // func1(3, 3);
 9int func1(int, double);  // func1(3, 3,0);
10int func1(double, int);  // func1(3.0, 3);
11int func1(double, double);  // func1(3.0, 3.0);
12
13// ---- Wrong ----
14double func1(int);  // return type differs, also matches func1(3); call
15int func1(int name1);  // parameter names differ, also matches func1(3); call

Function call matching

Function name overloading, default value, and implicit type conversion will all affect function call matching process. Any ambiguous function call will cause an syntax error.

  • call matching mechanism

    • return type does not matter

    • default value should be considered

    • Exact match: no implicit type conversion

    • Compatible match: need implicit type conversion

    • order of matching

      1. Exact matching

      2. Compatible matching

  • ambiguous matching

    • multiple exact matches

    • multiple compatible matches

    • an exact match will not conflict with compatible matches

 1// Wrong
 2// both exact matches
 3// func1(1); call is ambiguous with
 4void func1(int);
 5void func1(int, int = 1);
 6
 7// Wrong
 8// both compatible matches
 9// func2(2, 3); call is ambiguous with
10void func2(int, double);
11void func2(double, int);
12
13// Correct
14// first is an exact match
15// second is a compatible match
16// func2(2, 3.0); call is fine with
17void func2(int, double);
18void func2(double, double);

Example

 1#include <iostream>
 2
 3using namespace std;
 4
 5/**
 6  * function to double a value
 7  * myParam: the input value to be doubled
 8  * return: a double value
 9  * documentations should be above the declaration
10  */
11// int doubleValue(int = 10);  // default value, no name
12int doubleValue(int myParam = 10);  // default value, with name
13
14int doubleValue(int param1){ // parameter name can even be different
15  return param1 * 2;
16}
17
18int localFunc() {
19  cout << "This is local" << endl;
20  return 0;
21}
22
23int main() {
24  // function calls
25  cout << "double_value() gives " << doubleValue() << endl;  // get 20
26  cout << "double_value(5) gives " << doubleValue(5) << endl; // get 10
27
28  return EXIT_SUCCESS;
29}

Function Glossary

Function name

The name to a function given by the user. Same naming convention as variables. You cannot use a same name for a function and a variable either.

Function Parentheses

A pair of parentheses must be present to differentiate a function name from a variable name.

Function declaration

A specification of the return type, function name and parameter types. How a function can be called and what you can expect from the call.

Function definition

The implementation of the function. How is the work done in a function.

Function call

The syntaxes to invoke the function by providing actual parameters and optionally receive the returned value

Formal parameters

Sometimes referred as parameters. They are the names listed in the parentheses in the function definition. Each name should have a type specified. Formal parameters are stored in the same place as the local variables in the stack frame of the function call.

Actual parameters

The rvalues provided in the parenthesis in a function call.

Parameter Passing

A mechanism to initialize the value of formal parameters using the values of actual parameters provided in the function call.

Return statement

A statement employed in a function to exit the function and return a value (except in a void function).

Function overloading

The mechanism that allows multiple declarations using a same function name but different parameter list. Also applies to methods.

Function Call Matching

A mechanism to identify the right function definition to execute given a function call.

Scope

The lifespan of names of entities in C++(variables, functions, types, etc.) The C++ language has a block-based scope.