19.1 Introduction
We can break our C++ code into smaller chunks called functions. A
function has a return type, a name, a list of parameters in a declaration, and an additional function body in a definition. A simple function definition is:
type function_name(arguments) {
statement;
statement;
return something;
}
19.2 Function Declaration
To
declare a function, we need to specify a return type, a name, and a list of parameters, if any. To declare a function called
myfunction of type
void that accepts no parameters, we write:
Type
void is a type that represents
nothing, an empty set of values. To declare a function of type
int accepting one parameter, we can write:
int mysquarednumber (int x);
To declare a function of type
int, which accepts, for example, two
int parameters, we can write:
In function declaration only, we can omit the parameter names, but we need to specify their types:
19.3 Function Definition
To be called in a program, a function must be defined first. A function
definition has everything a function declaration has, plus the body of a function. Those are a return type, a function name, a list of function parameters, if any, and a function body. Example:
void myfunction(); // function declaration
// function definition
void myfunction() {
std::cout << "Hello World from a function.";
}
To define a function that accepts one parameter, we can write:
int mysquarednumber(int x); // function declaration
// function definition
int mysquarednumber(int x) {
return x * x;
}
To define a function that accepts two parameters, we can write:
int mysquarednumber(int x); // function declaration
// function definition
int mysquarednumber(int x) {
return x * x;
}
To call this function in our program, we specify the function name followed by
empty parentheses as the function has no parameters:
void myfunction(); // function declaration
int main()
{
myfunction(); // a call to a function
}
// function definition
void myfunction() {
std::cout << "Hello World from a function.";
}
To call a function that accepts one
parameter, we can use:
int mysquarednumber(int x); // function declaration
int main()
{
int myresult = mysquarednumber(2); // a call to the function
std::cout << "Number 2 squared is: " << myresult;
}
// function definition
int mysquarednumber(int x) {
return x * x;
}
We called a function mysquarednumber by its name and supplied a value of 2 in place of function parameter and assigned the result of a function to our myresult variable. What we pass into a function is often referred to as a function argument.
To call a function that accepts two or more
arguments, we use the function name followed by an opening parenthesis, followed by a list of arguments separated by commas and finally closing parentheses. Example:
int main()
{
int myresult = mysum(5, 10);
std::cout << "The sum of 5 and 10 is: " << myresult;
}
int mysum(int x, int y) {
return x + y;
}
19.4 Return Statement
Functions are of a certain type, also referred to as a
return type, and they must return a value. The value returned is specified by a
return-statement
. Functions of type
void do not need a
return statement. Example:
void voidfn()
{
std::cout << "This is void function and needs no return.";
}
Functions of other types (except function main) need a
return-statement:
int main()
{
std::cout << "The value of a function is: " << intfn();
}
int intfn()
{
return 42; // return statement
}
A function can have multiple
return-statements if required. Once any of the
return-statement is executed, the function stops, and the rest of the code in the function is ignored:
int multiplereturns(int x);
int main()
{
std::cout << "The value of a function is: " << multiplereturns(25);
}
int multiplereturns(int x)
{
if (x >= 42)
{
return x;
}
return 0;
}
19.5 Passing Arguments
There are different ways of passing arguments to a function. Here, we will describe the three most used.
19.5.1 Passing by Value/Copy
When we pass an argument to a function,
a copy of that argument is made and passed to the function if the function parameter type is not a reference. This means the value of the original argument does not change. A copy of the argument is made. Example:
void myfunction(int byvalue)
{
std::cout << "Argument passed by value: " << byvalue;
}
int main()
{
myfunction(123);
}
This is known as passing an argument by value or passing an argument by copy.
19.5.2 Passing by Reference
When a function parameter type is a reference type, then the actual argument is passed to the function. The function can modify the value of the argument.
Example:
void myfunction(int& byreference)
{
byreference++; // we can modify the value of the argument
std::cout << "Argument passed by reference: " << byreference;
}
int main()
{
int x = 123;
myfunction(x);
}
Here we passed an argument of a reference type int&, so the function now works with the actual argument and can change its value. When passing by reference, we need to pass the variable itself; we can’t pass in a literal representing a value. Passing by reference is best avoided.
19.5.3 Passing by Const Reference
What is preferred is passing an argument by
const reference
, also referred to as a
reference to const. It can be more efficient to pass an argument by reference, but to ensure it is not changed, we make it of const reference type. Example:
#include <iostream>
#include <string>
void myfunction(const std::string& byconstreference)
{
std::cout << "Arguments passed by const reference: " << byconstreference;
}
int main()
{
std::string s = "Hello World!";
myfunction(s);
}
We use passing by const reference for efficiency reasons, and the const modifier ensures the value of an argument will not be changed.
In the last three examples, we omitted the function declarations and only supplied the function definitions. Although a function definition is also a declaration, you should provide both the declaration and a definition as in:
#include <iostream>
#include <string>
void myfunction(const std::string& byconstreference);
int main()
{
std::string s = "Hello World!";
myfunction(s);
}
void myfunction(const std::string& byconstreference)
{
std::cout << "Arguments passed by const reference: " << byconstreference;
}
19.6 Function Overloading
We can have multiple functions with the same name but with different parameter types. This is called
function overloading. A simple explanation: when the function names are the same, but the parameter types differ, then we have
overloaded functions
. Example of a function overload declarations:
void myprint(char param);
void myprint(int param);
void myprint(double param);
Then we implement function definitions and call each one:
void myprint(char param);
void myprint(int param);
void myprint(double param);
int main()
{
myprint('c'); // calling char overload
myprint(123); // calling integer overload
myprint(456.789); // calling double overload
}
void myprint(char param)
{
std::cout << "Printing a character: " << param << '
';
}
void myprint(int param)
{
std::cout << "Printing an integer: " << param << '
';
}
void myprint(double param)
{
std::cout << "Printing a double: " << param << '
';
}
When calling our functions, a proper overload is selected based on the type of argument we supply. In the first call to myprint('c'), a char overload is selected because literal 'c' is of type char. In a second function call myprint(123), an integer overload is selected because the type of an argument 123 is int. And lastly, in our last function call myprint(456.789), a double overload is selected by a compiler as the argument 456.789 is of type double.
Yes, literals in C++ also have types, and the C++ Standard precisely defines what type that is. Some of the literals and their corresponding types:
'c' - char
123 - int
456.789 - double
true - boolean
"Hello" - const char[6]