FUNCTIONS IN THE C++ PROGRAMMING LANGUAGE
Lesson Content: Functions in C++
Welcome to the lesson on functions in the C++ language! Functions are the fundamental building blocks of any program, allowing code to be organized into smaller, easily understandable parts. In this lesson, we will explain how functions work, how to define and use them, and what their advantages are. We will cover different types of functions, including functions with and without return values, functions with parameters, function overloading, and recursion.
Programs written in the C++ programming language can contain a large number of statements, and if they were written one after another in a single file, developers would have difficulty navigating such code, making it hard to maintain. On the other hand, it often happens that a single algorithm, a set of statements that solve a small or large problem within an application, is repeated multiple times.
It can be concluded that it would be much better to extract that set of statements (part of the program) as a single unit, once as a subprogram or function, and then call that function whenever needed. Subprograms are a mechanism for breaking down complex problems into subproblems.
The C programming language recognizes only one type of subprogram, which is called a function.
You can find examples of functions on the following web page: Functions in C/C++ - Examples
There are three key aspects to understand about functions:
- Function Declaration
- Function Definition
- Function Call
Function Declaration
The function declaration (also known as the function prototype) is a way to inform the compiler in advance about the existence of a function, its return type, and its arguments. This is useful when the function is not implemented before its call in the code.
In programming, a declaration of a variable or function refers to defining its identifier and describing its properties without allocating memory space for storing the data or function. In the case of a function, the declaration specifies the return type and the number and types of arguments. In general, the declaration looks like this:
The function declaration is also known as a function prototype or a function signature.
If the function is located in the file above the main
function, as in the previous examples, then a separate declaration is not required. Otherwise, the declaration must be written above the main
function. For example, the prototype of the max
function would be:
or simply
The function prototype of promeni_ref
looks like this:
Example Code with Function Declaration
using namespace std;
// Function declaration that calculates the sum of two numbers
int sum(int a, int b);
int main() {
cout << "The sum is: " << result << endl;
return 0; // End of program
// Definition of the sum function that returns the sum of two numbers
int sum(int a, int b) {
Defining functions
Example of a function definition
int product(int x, int y) {
- Function commands
- function header
- the body of the function
Example 1: Finding the maximum of two integers
- The function header contains the return type, function name, and argument list.
- The function body contains the logic of the function.
In the method header, there are two words.
The first one, in this case, int
, represents the data type of the return value. This method, which calculates the larger number between two integers, returns that number, whose type is int
. This is the return type.
The second word is the method name, which is chosen by the programmer and should suggest the purpose of the method.
The method body is enclosed in curly braces. Inside the body, the function’s statements are written.
In the function (method) header, after the name, the function parameters (arguments) are placed inside parentheses. These are the data that need to be provided to the function so it can complete the given task.
In the previous example, the task of the function is to determine the maximum between two integers, and the data that needs to be provided to the function via parameters are those two numbers, in this case, denoted as a
and b
.
The following image provides a more detailed view of this method.
A function can have zero, one, or multiple parameters. If a function does not require input data, the parentheses in the function header will remain empty.
If a method does not return a value, it will not have a return
statement with data in its body, but it may contain just return
. In such cases, the return type is specified as void
.
A program must have at least one function, which is the main
(main) function. An example of the main
function from the previous example is shown in the image below.
Inside the main
function, two integer numbers are first read, and then the maximum is determined. The statements that determine the maximum are separated into a special method called max
(see image 2).
In the main
function, the cout
statement is used to print this value. At the place where the data for printing is expected, there is a call to the max
function. The values A
and B
are passed as parameters, which are actually copies of these values.
The max
function determines the larger value and returns it as a return value. This return value will be printed together with the text "The larger number is" in the output.
After running the program and entering the values, for example, 5 and 10 for A
and B
, the output will be:
Function call
- Inside the main() function.
- Within other functions.
An example of a function call in main():
using namespace std;
// Declaration of a function that calculates the square of a number
int square(int number);
int main() {
cout << "The square of " << number << " is: " << square(number) << endl;
return 0;
// Definition of a function that calculates the square of a number
int square(int number) {
- Function declaration: square takes a single integer and returns its square.
- Main function (main): Loads the number 4, calls the square function and prints the result.
- Function definition: square calculates the product of a number with itself, which is the square of that number.
Calling functions inside other functions:
using namespace std;
// Function declarations
int sum(int a, int b);
int square_of_sum(int a, int b);
int main() {
cout << "The square of the sum is: " << result << endl;
return 0;
// Definition of a function that calculates the sum of two numbers
int sum(int a, int b) {
// Definition of a function that calculates the square of the sum of two numbers
int square_of_sum(int a, int b) {
return s * s;
- Function declarations: The function sum calculates the sum of two numbers, while square_sum calculates the square of the sum of two numbers.
- Main function (main): Calls the square_sum function with the numbers 3 and 4, and prints the result on the screen.
- Function definition:
- sum returns the sum of two numbers.
- sum_square uses the sum function to calculate the sum and then returns the square of that sum.
- sum returns the sum of two numbers.
Test your code in the editor below!
More detailed explanation of function calls in the example "Determining the maximum of two numbers". Continuation of the task.
In the example shown in image 3, the max function is called:
cout << "The greater number is " << max(A, B);
The declaration of a function call generally looks like this:
function_name(parameter1, parameter2, ...);
The parameters passed to the function are copied in order into the parameters defined in the function definition (see image 2). In the function definition, the data type is placed in front of the parameter name:
int max(int a, int b)
Here, new memory is actually reserved labeled as a and b, which takes the copies of the parameter values from the function call:
max(A, B);
The data type is not specified before the parameter in the function call. The copying of parameters is shown in image 5.
Example 1-continued: Subtracting the maximum of two numbers-code
Load two integers and determine their maximum using the previously defined function.
using namespace std;
// Function that determines the maximum between two numbers
int max(int a, int b) {
int main() {
cout << "Enter the first number: ";
cin >> number1;
cout << "Enter the second number: ";
cin >> number2;
cout << "The greater number is: " << max(number1, number2) << endl;
return 0; // End of the program
Passing a parameter by value and by reference
We can illustrate this through the following example:
Example 2: Substitution of data value
Let's create a function that will change the value of the sent data:
This value did change inside the change_vr function, but this change is not reflected in the data in the main function.
For this to be correct, the parameters must be passed by reference.
Passing function parameters by reference
using namespace std;
// Function to change value by reference
void change_ref(int& a) {
cout << "Function change_ref, a=" << a << endl;
int main() {
cin >> a;
cout << "a=" << a << endl;
change_ref(a);
cout << "After change: a=" << a << endl;
return 0;
a= 10
Function change_ref, a= 200
After change: a= 200
Function Parameter Passing by Pointer
Instead of references, pointers to data can also be used. The effect is similar to passing by reference, meaning that changes made inside the function to the data accessed through the pointer will reflect on the original data defined in the main function. This happens because pointers point to the original data, not to a new one that just has the same value as the original.
More about pointers can be found in the Pointers in C++ lesson.
Code Example:
using namespace std; // Using the std namespace
/*
void change_value(int pr){
pr = 200; // This function does not change the original variable because the parameter is passed by value
}
*/void change_by_pointer(int *pr){ // Function takes a pointer to int
cout << "In function: " << (*pr) << endl; // Displaying the new value in the function
int main() { // Main function of the program
x = 30; // Setting the initial value
cout << x << endl; // Displaying the original value
// change_value(x); // This call would leave x unchanged
change_by_pointer(&x); // Passing the address of x to the function
cout << x << endl; // Displaying the new value of x after the function call
return 0; // End of the program
Output:
In function: 200
200
Examples of Functions with Different Return Types and Arguments
1. Function with no return value (void)
Functions that do not return a value use the return type void
. They are used for performing actions, such as printing output to the screen.
Example:
int main() {
return 0;
Explanation:
- The
greet
function does not return a value because it uses the return typevoid
. - It performs only one action - printing a message.
2. Function with return type int
The function can return numerical values that are used in the further course of the program.
Code:
int main() {
cout << "The sum is: " << result << endl;
return 0;
Explanation:
- The
sum
function takes two arguments (a
andb
) and returns their sum as the result.
3. Function with return type double
This is used when decimal numbers are required, for example, in mathematical calculations.
Code:
int main() {
double area = circleArea(r);
cout << "The area of the circle is: " << area << endl;
return 0;
Explanation:
- The
circleArea
function calculates the area of a circle using the formulaπ · r²
and returns the result as adouble
.
4. Function with return type string
Used for working with textual values.
Code:
int main() {
cout << greetingMessage(name) << endl;
return 0;
Explanation:
- The
greetingMessage
function takes a textual argument and returns a personalized message.
Recursive functions
Recursive functions are functions that call themselves, either directly or indirectly. This approach allows solving problems that can naturally be divided into smaller subproblems.
For a more detailed explanation and practical examples, visit our page: Recursive Algorithms.
Video lesson: Functions in the C++ language
Common Mistakes and Tips
When working with functions in C++, certain mistakes frequently occur. Here are some examples along with tips on how to avoid them:
Most Common Mistakes When Working with Functions
-
Forgotten function declaration: If a function is not declared before being called, the compiler will not recognize it.
Tip: Always declare functions before the main function main() or use header files. -
Argument type mismatch: Passing arguments of the wrong type can cause errors.
Tip: Check argument types and ensure they match the function declaration. -
Missing return value: You declared a function to return a value but forgot the
return
statement.
Tip: Always verify that the function returns a value if its return type is notvoid
. -
Recursion without a base case: If a function lacks a condition to stop recursion, it will result in infinite calls.
Tip: Always define a base case (termination condition) for recursive functions.
Connecting with Object-Oriented Concepts
In object-oriented programming (OOP), functions play a key role as part of classes and objects:
Functions and OOP in C++
Within classes, functions are called methods. They allow objects to perform tasks and manipulate their data.
Example:
using namespace std;
class Circle {
double radius;
public:
// Constructor to initialize the radius
Circle(double r) {
// Method to calculate the area
double area() {
int main() {
Circle c(5.0);
// Calling the method
cout << "The area of the circle is: " << c.area() << endl;
return 0;
Methods like area()
enable encapsulation of logic within classes, making the code more modular and readable.
Class Circle: Defines the private data member radius
and the public method area()
, which calculates the area of the circle.
Constructor: Initializes radius
when creating an object.
Method area(): Returns the area of the circle using the formula π r2.
Main function: Creates an object of the Circle
class, calls the area()
method, and prints the result.
Function Overloading
Function overloading allows defining multiple functions with the same name but with different numbers or types of parameters. This enables more intuitive function calls with various data types.
#include <iostream>
using namespace std;
void print(int number) {
cout << "Integer value: " << number << endl;
}
void print(std::string text) {
cout << "String value: " << text << endl;
}
int main() {
print(42);
print("Hello");
return 0;
}
Inline Functions
Inline functions are those that expand directly into the code instead of being called, which can improve performance for very small functions. They are defined using the inline
keyword.
#include <iostream>
using namespace std;
inline int add(int a, int b) {
return a + b;
}
int main() {
int result = add(3, 4);
cout << "Result: " << result << endl;
return 0;
}
Nested Functions (Lambda Expressions)
C++ does not support nested functions in the traditional sense, but lambda expressions allow defining functions within other functions. This is often used for short operations executed within a function.
#include <iostream>
using namespace std;
int main() {
// Lambda function for adding two numbers
auto add = [](int a, int b) -> int {
return a + b;
};
int result = add(10, 20);
cout << "Lambda function result: " << result << endl;
return 0;
}
Explanation:
Function Overloading: In the example above, the function print
is overloaded to handle both integer and string values. This allows for more flexible use of the same function with different data types.
Inline Functions: The function add
is declared as inline, meaning its code is inserted directly at the call site, reducing function call overhead, which is useful for simple operations.
Nested Functions (Lambda Expressions): Although C++ does not support traditional nested functions, lambda expressions enable defining functions within functions. In the example above, the lambda function add
is defined inside the main
function and is used for adding two numbers.
Function Overloading
Function overloading allows defining multiple functions with the same name but with different numbers or types of parameters. This enables more intuitive function calls with various data types.
#include <iostream>
using namespace std;
void print(int number) {
cout << "Integer value: " << broj << endl;
}
void print(std::string text) {
cout << "String value: " << text << endl;
}
int main() {
print(42);
print("Hello");
return 0;
}
Inline Functions
Inline functions are those that expand directly into the code instead of being called, which can improve performance for very small functions. They are defined using the inline
keyword.
#include <iostream>
using namespace std;
inline int add(int a, int b) {
return a + b;
}
int main() {
int result = add(3, 4);
cout << "Result: " << result << endl;
return 0;
}
Nested Functions (Lambda Expressions)
C++ does not support nested functions in the traditional sense, but lambda expressions allow defining functions within other functions. This is often used for short operations executed within a function.
#include <iostream>
using namespace std;
int main() {
// Lambda function for adding two numbers
auto add = [](int a, int b) -> int {
return a + b;
};
int result = add(10, 20);
cout << "Lambda function result: " << result << endl;
return 0;
}
Explanation:
Function Overloading: In the example above, the function ispisi
is overloaded to handle both integer and string values. This allows for more flexible use of the same function with different data types.
Inline Functions: The function saberi
is declared as inline, meaning its code is inserted directly at the call site, reducing function call overhead, which is useful for simple operations.
Nested Functions (Lambda Expressions): Although C++ does not support traditional nested functions, lambda expressions enable defining functions within functions. In the example above, the lambda function saberi
is defined inside the main
function and is used for adding two numbers.
Example of Using Functions in Larger Projects
In larger projects, functions are used to organize code, improve readability, and facilitate easier maintenance. For example, let's consider a simulation of a student data management system.
Project Structure
- main.cpp – The main file that runs the program
- student.hpp / student.cpp – Classes and functions for working with students
- database.hpp / database.cpp – Functions for database manipulation
Implementation
Below is a simplified example of how functions are used to organize student-related operations.
student.hpp (Student Structure Definition)
#ifndef STUDENT_HPP
#define STUDENT_HPP
#include <iostream>
#include <string>
struct Student {
std::string firstName;
std::string lastName;
int index;
void showData();
};
#endif
student.cpp (Method Implementation)
#include "student.hpp"
void Student::showData() {
std::cout << "Student: " << firstName << " " << lastName << ", Index: " << index << std::endl;
}
database.hpp (Function Declarations for Student Management)
#ifndef DATABASE_HPP
#define DATABASE_HPP
#include "student.hpp"
#include <vector>
class Database {
private:
std::vector<Student> students;
public:
void addStudent(const Student& s);
void showAllStudents();
};
#endif
database.cpp (Function Implementation)
#include "database.hpp"
#include <iostream>
void Database::addStudent(const Student& s) {
students.push_back(s);
}
void Database::showAllStudents() {
for (const auto& s : students) {
s.showData();
}
}
main.cpp (Main Program)
#include "database.hpp"
int main() {
Database db;
Student s1 = {"Marko", "Marković", 202301};
Student s2 = {"Ana", "Anić", 202302};
db.addStudent(s1);
db.addStudent(s2);
db.showAllStudents();
return 0;
}
Explanation
- By using separate files for different components, the code becomes modular and easier to maintain.
- The Database class enables working with a collection of students, while individual student operations are handled through the Student class.
- Functions help isolate specific operations, increasing code reusability.
Additional Resources
-
cppreference.com - Functions
Detailed documentation with examples on functions in C++. -
GeeksforGeeks - Functions in C++
Practical examples and explanations of functions in C++. -
LearnCpp - Functions
A comprehensive guide to learning functions and other concepts of C++. -
Programming World - Main Page
Local resources in Serbian for programmers. -
Recursive Algorithms in C++
A page dedicated to recursion and its application in programming.
For additional questions and explanations, contact us via the contact form.