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
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
Exact matching
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.