Category: 3. Functions

https://cdn3d.iconscout.com/3d/premium/thumb/function-3d-illustration-download-in-png-blend-fbx-gltf-file-formats–cogwheel-service-cog-miscellaneous-pack-illustrations-4312348.png?f=webp

  • Function Overriding in C++

    A function is a collection of code blocks with instructions inside, which is used for specific tasks. It is meant to be reused as per requirement, making the division of complex problems into smaller and manageable pieces.

    What is Function Overriding in C++?

    Function overriding is a concept of object-oriented programming which allows a derived class to redefine a function that is already defined in the base class.

    Here the method’s name and parameters remain the same, but the derived class changes its behavior to suit their specific needs.

    Example

    Let’s consider these 2 functions; one is base class (a) and another is derived class (b), and the function (c) is the main(), where we are implementing overriding −

    Function (a)

    classbase{public:voidnotice()
       cout <<"This is my Base Class";}

    Function (b)

    classderived:public base{public:voidnotice()
    
      cout &lt;&lt;"This is my Derived Class";}</code></pre>

    Function (c)

    voidmain(){// creating an object for base class and calling it
       base b;
       b.notice();// creating an object for derived class and calling it 
       derived d ;
       d.notice();}

    Overriding Explanation

    • Here, we have created an object of base and derived class of 'function (a) and function(b)' respectively and called them inside function (c) as shown, "b.notice() and d.notice()" respectively.
    • In this case, for derived class d.notice() will be executed first because it represents the most up-to-date or updated version of the function
    • However, if we create an object of the base class as shown in function(c) "b.msg()" and call it, it will use the original version from the base class.

    In short, function overriding occurs when the functionality of the base class is redefined in the derived class. When an object of the derived class is created, it will call the updated function from the derived class, meaning that the base class function (a) is overridden by the derived class function (b).

    Function overriding is an essential concept in object-oriented programming, enabling polymorphism and dynamic binding.

    Example of Function Overriding

    Below is a simple example illustrating how overriding works

    #include <iostream>usingnamespace std;// Base classclassShape{public:// Virtual method to be overriddenvirtualvoiddraw()const{
    
         cout &lt;&lt;"Drawing a shape"&lt;&lt; endl;}};// Derived class CircleclassCircle:public Shape{public:// Overriding the base class methodvoiddraw()constoverride{
         cout &lt;&lt;"Drawing a circle"&lt;&lt; endl;}};// Derived class SquareclassSquare:public Shape{public:// Overriding the base class methodvoiddraw()constoverride{
         cout &lt;&lt;"Drawing a square"&lt;&lt; endl;}};// Main functionintmain(){
    Shape* shapePtr; Circle circle; Square square;// Point to Circle and call draw() shapePtr =&circle; shapePtr->draw();// Outputs: Drawing a circle// Point to Square and call draw() shapePtr = □ shapePtr->draw();// Outputs: Drawing a squarereturn0;}

    Output

    Drawing a circle
    Drawing a square
    

    Function Overriding Vs. Function Overloading

    Although Function Overriding and Function Overloading are essential key-concepts of Object-oriented programming in C++, they both do serve different purposes.

    Function overriding allows derived class to get new implementation of method to its previously defined base class, as having different scopes(base class and derived class) where it resolved at runtime polymorphism(dynamic binding), it only take place in presence of inheritance and can overridden just once, where execution speed relatively slower.

    Whereas, function overloading enables you to create multiple functions with the same name but different parameter lists within the same scope. It is resolved at compile time polymorphism (static binding), where presence of inheritance is not important, These functions can be overloaded multiple times and execution speed tends to be faster comparatively.

    Advanced Overriding Concepts

    Here’s a list of additional sub topics covering advanced overriding concepts −

    1. Virtual Destructor

    A virtual destructor makes sure that the destructor of the derived class will be executed when an object is removed through a base class pointer. Function overriding with virtual destructors avoids resource leaks and unpredictable behavior by ensuring proper deletion of objects through base class pointers.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;classBaseClass{public:virtual~BaseClass(){// Virtual destructor
    
         cout &lt;&lt;"BaseClass destructor"&lt;&lt; endl;}};classDerivedClass:public BaseClass{public:~DerivedClass()override{// Overriding destructor
         cout &lt;&lt;"DerivedClass destructor"&lt;&lt; endl;}};intmain(){
    BaseClass* a =newDerivedClass();// Calls DerivedClass's destructor followed// by BaseClass's destructordelete a;return0;}

    Output

    DerivedClass destructor
    BaseClass destructor
    

    2. Covariant Return Value Types

    Covariant return types allow derived classes to override a method and return a more specific type than the base class method. This means that a derived class can return a pointer or reference to a more derived type, rather than just the base type. Function overriding improves flexibility and precision in object-oriented programming.

    Note

    In the derived class, the return type must be a pointer or reference to a type that is derived from the return type of the base class.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;classVehicle{public:// Final methodvirtualvoidhonk()final{
    
         cout &lt;&lt;"Vehicle honk: Beep beep!"&lt;&lt; endl;}};classSportsCar:public Vehicle{// Cannot override honk() here};intmain(){
    Vehicle* v =newSportsCar(); v->honk();// Calls Vehicle's honk() methoddelete v;return0;}

    Output

    Vehicle honk: Beep beep!
    

    3. Overriding and final Keyword alternate word

    The final keyword stops any further subclassing of a class or overriding of a method.

    Function overriding with the final keyword is important because it guarantees that a class or method cannot be further changed or extended.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;classSubject{public:// Final methodvirtualvoidexamType()final{
    
         cout &lt;&lt;"This subject has a written exam."&lt;&lt; endl;}};classMath:public Subject{// Cannot override examType() here};intmain(){
    Subject* s =newMath(); s->examType();// Calls Subject's examType() methoddelete s;return0;}

    Output

    This subject has a written exam.
    

    4. Virtual Inheritance

    Virtual inheritance in C++ tackles problems which arise with multiple inheritance, particularly the diamond problem. It ensures that when a class inherits from several base classes which have a common ancestor, only a single instance of that common base class is created.

    Virtual inheritance makes sure that only one copy of a base class is used when multiple derived classes share that base class in a hierarchy.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;classBase{public:voidpresent(){ cout <<"Display from Base class"<< endl;}};classA:virtual public Base{};classB:virtual public Base{};classFinal:public A, public B{public:voidget(){ cout <<"Display from Final class"<< endl;}};intmain(){
       Final obj;// Displays: Display from Base class
       obj.present();// Displays: Display from Final class
       obj.get();return0;}

    Output

    Display from Base class
    Display from Final class
    

    Advantages of Function Overriding

    1. Polymorphism

    Overriding enables polymorphism by letting objects of different derived classes be treated as instances of a base class. This allows dynamic method binding at runtime, where the correct method implementation is chosen based on the object type, thus enhancing flexibility and adaptability, making it a fundamental component of polymorphism.

    2. Code Reusability

    Developers can utilize existing code by inheriting methods from a base class and customizing them in derived classes. This approach fosters a more streamlined and organized code structure.

    3. Maintainability

    Overriding promotes a modular design by encapsulating various functionalities within distinct classes. This approach simplifies understanding, maintaining, updating and extending the code.

    4. Design Patterns

    Overriding plays a key role in the Template Method pattern by defining the overall structure of an algorithm in a base class, while permitting subclasses to override specific steps.

    The Strategy pattern leverages overriding to encapsulate various algorithms and enable their interchange at runtime.

    5. Memory Management

    When using inheritance and dynamic memory allocation, virtual destructors are vital for proper memory management. Overriding the destructor in derived classes ensures that resources allocated by the base and derived classes are correctly deallocated, which prevents memory leaks and ensures clean resource release.

  • Function Overloading in C++

    Function overloading in C++ allows you to define multiple functions with the same name but different parameters. Function overloading is used to achieve polymorphism which is an important concept of object-oriented programming systems.

    Syntax for Overloaded Functions

    Consider the following two function declarations having the same name but different parameters −

    return_type function_name(parameter1);
    return_type function_name(parameter2);

    Example of Function Overloading

    In the following example, we are defining three different functions with the same name but different parameters. This example demonstrates the implementation of function overloading −

    Open Compiler

    #include<iostream>usingnamespace std;// Adding two integers (Function definition 1)intaddition(int a,int b){return a + b;}// Adding three integers (Function definition 2)intaddition(int a,int b,int c){return a + b + c;}// Adding two floating-point numbers (Function definition 3)floataddition(float a,float b){return a + b;}intmain(){
       cout<<addition(10.5f,20.3f)<<endl;
       cout<<addition(10,20,30)<<endl;
       cout<<addition(10,20)<<endl;return0;}

    Output

    30.8
    60
    30
    

    How Function Overloading Works?

    In the case of different functions with the same name (function overloading), when the compiler reaches a specific function call, it checks with the different function definition based on the parameters type, order, or number of arguments, and executes the matched function definition.

    Example

    Let suppose, there are 3 different function definitions to add numbers with different parameters −

    // Adding two integers (Function definition 1)intaddition(int a,int b){return a + b;}// Adding three integers (Function definition 2)intaddition(int a,int b,int c){return a + b + c;}// Adding two floating-point numbers (Function definition 3)floataddition(float a,float b){return a + b;}

    And, you call the function in the following order −

    addition(10.5f, 20.3f); // Function call 1
    addition(10, 20, 30); // Function call 2
    addition(10, 20); // Function call 3
    

    In the above function calls, function definition will be called in the following order −

    • Function call 1 will execute Function definition 3, because here we are passing two float values.
    • Function call 2 will execute Function definition 2, because here we are passing three integer values.
    • Function call 3 will execute Function definition 1, because here we are passing two integer values.

    Function Overloading Based on Number of Parameters

    This method involves defining multiple functions with the same name but a different number of parameters.

    Syntax

    voiddisplay(int a);// takes one parametervoiddisplay(int a,double b);// takes two parameters

    Example

    The following example demonstrates the function overloading based on the number of parameters −

    #include <iostream>usingnamespace std;// Function overloads based on the number of parametersvoiddisplay(int a){
       cout <<"Display with one integer: "<< a << endl;}voiddisplay(int a,double b){
       cout <<"Display with an integer and a double: "<< a <<" and "<< b << endl;}intmain(){// Calls the first overloaddisplay(10);// Calls the second overloaddisplay(10,3.14);double:10and3.14return0;}

    Output

    Display with one integer: 10
    Display with an integer and a double: 10 and 3.14
    

    Function Overloading Based on Different Parameter Types

    This method involves defining multiple functions with the same name but different types of parameters.

    Syntax

    voidshow(int a);// parameter with int type voidshow(double a);// parameter with double type

    Example

    The following example demonstrates the function overloading based on the different parameter types −

    Open Compiler

    #include <iostream>usingnamespace std;// Function for integer inputvoidshow(int a){
       cout <<"Integer value: "<< a << std::endl;}// Function for double inputvoidshow(double a){
       cout <<"Double value: "<< a << std::endl;}intmain(){show(10);show(3.14);return0;}

    Output

    Integer value: 10
    Double value: 3.14
    

    Function Overloading Based on Different Parameter Order

    This method involves defining multiple functions with the same name but different sequences of parameters.

    Syntax

    // integer followed by a double, // can be any datatype(bool, char etc)voiddisplay(int a,double b){ 
       cout <<"Integer and Double: "<< a <<", "<< b << endl;}// double followed by an integervoiddisplay(double a,int b){  
       cout <<"Double and Integer: "<< a <<", "<< b << endl;}

    Example

    The following example demonstrates the function overloading based on the different parameter order −

    Open Compiler

    #include <iostream>usingnamespace std;voiddisplay(int a,double b){
       cout <<"Integer and Double: "<< a <<", "<< b << endl;}voiddisplay(double a,int b){
       cout <<"Double and Integer: "<< a <<", "<< b <<endl;}intmain(){display(10,3.14);display(3.14,10);return0;}

    Output

    Integer and Double: 10, 3.14
    Double and Integer: 3.14, 10
    

    Use Cases for Function Overloading

    Function overloading in C++ is a powerful feature that allows you to use the same function name to perform different tasks based on different parameter lists. This can lead to more readable and maintainable code. Here are some common scenarios and examples where function overloading is useful −

    • Different Data Types − Function overloading is useful for handling various data types with a common function name.
    • Different Number of Parameters − Function overloading provides flexibility with functions which have varying numbers of parameters.
    • Parameter Type and Order − Function overloading handles different parameter types or their order.
    • Different Operations − Function overloading supports similar operations for different data types or contexts.
    • Variant Contexts − Function overloading provides variations of a function to suit different requirements or levels of detail.
  • Return Statement in C++

    The return statement in C++ is used to exit a function and to send a value back to the function’s caller which is optional depending on requirement. It plays a very important role in controlling the flow of a program and making sure that functions will provide results to other parts of the code.

    Syntax

    Below is the syntax of using return statement in C++ −

    return[expression];

    Where, “expression” is optional, specifically used for function. If provided, it specifies the value to be returned to the caller.

    Example of return Statement

    The following is an example of return statement −

    Open Compiler

    #include <iostream>usingnamespace std;intsum(int a,int b){// Here, returning sum of a and breturn a + b;}intmain(){// Calling the functionint ans =sum(5,2);
       cout <<"The sum of two integers 5 and 2 is:  "<< ans << endl;// Returning from the main (),// 0 represents execution done without any errorreturn0;}

    Output

    The sum of two integers 5 and 2 is:  7
    
    
    

    Key Aspects of return Statement

    1. Function Termination

    When a return statement is executed, the function exits immediately, and optionally sends value back to the caller.

    2. Returning Types

    Return by Value

    In this the specified value in return statement is sent back to the caller. This is essential for functions which perform calculations or need to provide results.

    intAdd(int a,int b){return a + b;// Returns the sum of a and b}

    No Return Value (void)

    The functions which are declared with void, the return statement can be used without an expression to exit the function early.

    voidGetMessage(){
       cout <<"Hello, TutorialsPoint Learner!";return;// Exits the function}

    3. Multiple return Statements

    A function may consist of multiple return statements, which we generally get to see within conditional statements.

    intmax(int a,int b){if(a > b)return a;elsereturn b;}

    4. Returning Objects

    Functions can return objects, which can be useful for returning multiple values encapsulated in a class or struct.

    structpoint{int x, y;};
    
    point getOrigin(){return{0,0};}

    5. Early Exit

    The return statement can be used to exit a function early, which is useful for error handling or special conditions.

    intdivideInteger(int a,int b){if(b ==0){
    
      cer &lt;&lt;"Error: Division by zero!"&lt;&lt; endl;return-1;// Shows an error}return a / b;}</code></pre>

    Return Types and Value Handling in C++

    In C++, the return type of a function determines what kind of value (if any) a function will return to the caller. Proper handling of return types and values is important for making sure that functions behave as expected and integrate smoothly with other parts of the program.

    1. Primitive Data Types

    Primitive data types are the basic built-in types provided by C++. Common examples are like int, float, double, char etc.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;// created a function which returns an integerintgetSquare(int num){return num * num;}intmain(){int value =5;int result =getSquare(value);// Calling the function and storing its result
       cout <<"The square of "<< value <<" is "<< result << endl;return0;}
    Output
    The square of 5 is 25
    

    2. User-Defined Types

    User-defined types include structs and classes. These types allow you to define complex data structures and customize them as per your specific requirements.

    Example with Struct

    Open Compiler

    #include <iostream>usingnamespace std;structPoint{int x;int y;};
    Point createPoint(int x,int y){
       Point p;
       p.x = x;
       p.y = y;return p;// will returns a Point object}intmain(){
       Point p =createPoint(10,20);
       cout <<"Point coordinates: ("<< p.x <<", "<< p.y <<")"<< endl;return0;}
    Output
    Point coordinates: (10, 20)
    

    Example with Classes

    Open Compiler

    #include <iostream>usingnamespace std;classrectangle{public:rectangle(int w,int h):width(w),height(h){}intgetArea()const{return width * height;}private:int width;int height;};
    
    rectangle createRectangle(int width,int height){returnrectangle(width, height);// Returns a Rectangle object}intmain(){
       rectangle rect =createRectangle(10,5);
       cout <<"Area of given Rectangle is: "<< rect.getArea()<< endl;return0;}
    Output
    Area of given Rectangle is: 50
    

    3. References and Pointers

    References and pointers are used to refer to variables or objects without making any copies. Which can be useful for efficiency and and easy to modify the original data when needed.

    Returning by Reference

    Open Compiler

    #include <iostream>usingnamespace std;int globalValue =100;int&getGlobalValue(){return globalValue;// Returns a reference to the global variable}intmain(){int& ref =getGlobalValue();
       ref =200;// Modifies the global variable
       cout <<"Global Value: "<< globalValue << endl;return0;}
    Output
    Global Value: 200
    

    Returning by Pointer

    Open Compiler

    #include <iostream>usingnamespace std;int*createArray(int size){int* array =newint[size];// Allocating memory dynamicallyfor(int i =0; i < size;++i){
    
      array&#91;i]= i *10;}return array;// Returning a pointer to the allocated array}intmain(){int* myArray =createArray(5);for(int i =0; i &lt;5;++i){
      cout &lt;&lt; myArray&#91;i]&lt;&lt;" ";}delete&#91;] myArray;// Free dynamically allocated memoryreturn0;}</code></pre>
    Output
    0 10 20 30 40 
    
  • Recursion (Recursive Function)

    Recursion is a programming technique where a function calls itself over again and again with modified arguments until it reaches its base case, where the recursion stops.

    It breaks a problem down into smaller, more manageable sub-problems, recursion allows for elegant and better solutions to complex problems.

    Recursive Function

    A recursive function is a function which is particularly used for recursion where a function calls itself, either directly or indirectly, to address a problem. It must include at least one base case to terminate the recursion and one recursive case where the function invokes itself.

    • Base Case − It’s a case where recursion stops or ends after reaching that particular condition.
    • Recursive Case − It’s a case where a function calls itself over again with decremented value until and unless it reaches its base case.

    Creating a Recursive Function

    The following syntax is used to implement a recursive function in C++ −

    function name(param_1, param_2..){<base condition><function body><return statement>}

    Here,

    • Where, function name(param_1, param_2..) is a function declared as “name” passing with multiple parameters in it as per requirement.
    • Now the function body is being divided into three sub-categories : base condition, function body and return statement.
    • In base condition we will define its base case, where recursion has to stop or end.
    • In the function body, a recursive case will be defined, where we need to call the function over again and again as per requirement.
    • At last, the return statement will return the final output of the function.

    Explore our latest online courses and learn new skills at your own pace. Enroll and become a certified expert to boost your career.

    Calling a Recursive Function

    Calling a recursive function is just like calling any other function, where you will use the function’s name and provide the necessary parameters in int main() body.

    To call a recursive function, use the following syntax −

    func_name(value);

    Example of Recursion

    Below is an example of a recursion function in C++. Here, we are calculating the factorial of a number using the recursion −

    #include <iostream>usingnamespace std;// Recursive Function to Calculate Factorialintfactorial(int num){// Base caseif(num <=1){return1;}// Recursive caseelse{return num *factorial(num -1);}}intmain(){int positive_number;
       cout <<"Enter a positive integer: ";
       cin >> positive_number;if(positive_number <0){
    
      cout &lt;&lt;"Wrong Input, Factorial is not Defined for Negative Integer"&lt;&lt; endl;}else{
      cout &lt;&lt;"Factorial of "&lt;&lt; positive_number &lt;&lt;" is "&lt;&lt;factorial(positive_number)&lt;&lt; endl;}return0;}</code></pre>

    Output

    Enter a positive integer: 4 (input)
    Factorial of 4 is 24
    

    Explanation

    If take input int positive_number as 4, It will send integer to function name 'factorial' as factorial(4)

    Initial Call: factorial(4)

    This function will check base case (n<=1), as it’s not satisfying the base case, therefore move forward to recursive case and will compute as "4 * factorial(3)".

    Second call: factorial(3)

    This function will again check base case, as it’s not satisfying it, therefor will again move forward to recursive case , and compute as "3 * factorial(2)".

    Third Call: factorial(2)

    Checks base case and computes "2 * factorial(1)"

    Fourth call: factorial(1)

    Checks base case, now since function satisfying this base case condition that’s less than or equal to 1, So it will return 1.

    Unwinding the Stack

    Now, the recursive calls will start returning: After the 4th call now it will again start from back, returning to the Third Call first.

    Return to Third Call: factorial(2)

    We already have factorial(1) = 1, therefor factorial(2) will return, "2 * factorial(1)", that’s "2 * 1" , which returns as factorial(2) equals to 2.

    Return to Second Call: factorial(3)

    Now, factorial(2) is 2, therefore factorial(3) equals to "3 * 2", that’s 6.

    Return to Initial Call: factorial(4)

    We have factoria(3) which returns 6, therefore, factorial(4) returns "4 * 6 = 24".

    Types of Recursion

    Recursion can be categorized into two main types where each with its own sub-categories −

    1. Direct Recursion

    Direct recursion occurs when a function calls itself directly −

    Simple Direct Recursion

    The function calls itself with a simpler or smaller instance of the problem. It is used for solving problems like factorial calculation, fibonacci sequence generation, etc.

    Tail Recursion

    A form of direct recursion where the recursive call is the last operation in the function. It is used for solving accumulative calculations and list processing problems.

    intfactorial(int n,int result =1){if(n <=1){return result;}else{returnfactorial(n -1, n * result);// Tail recursive call}}

    Head Recursion

    The recursive call is made before any other operation in the function. Processing occurs after the recursive call returns. It is used for tree traversals and output generation.

    voidprintNumbers(int n){if(n >0){printNumbers(n -1);// Recursive call first
    
      cout &lt;&lt; n &lt;&lt;" ";// Processing after recursive call}}</code></pre>

    Linear Recursion

    Each function call generates exactly one recursive call, forming a linear chain of calls. It is used for simple counting or summing.

    intlinearRecursion(int n){if(n <=0){return0;}else{returnlinearRecursion(n -1)+1;// Linear recursive call}}

    2. Indirect Recursion

    Indirect recursion occurs when a function calls another function, which eventually leads to the original function being called. This involves two or more functions calling each other.

    Mutual Recursion

    In mutual recursion, two or more functions call each other in a recursive manner, forming a cyclic dependency. It is used for even and odd number classification and grammar parsing.

    Open Compiler

    #include <iostream>usingnamespace std;voideven(int n);voidodd(int n);voideven(int n){if(n ==0){
    
      cout &lt;&lt;"Even"&lt;&lt; endl;}else{odd(n -1);// Calls odd}}voidodd(int n){if(n ==0){
      cout &lt;&lt;"Odd"&lt;&lt; endl;}else{even(n -1);// Calls even}}intmain(){even(4);// Outputs: Evenodd(5);// Outputs: Oddreturn0;}</code></pre>
    Output
    Even
    Even
    

    Nested Recursion

    The nested recursion is a form of indirect recursion where a recursive function makes another recursive call inside its own recursive call. It is used for solving complex mathematical and algorithmic problems.

    Open Compiler

    #include <iostream>usingnamespace std;intnestedRecursion(int n){if(n >100){return n -10;}else{returnnestedRecursion(nestedRecursion(n +11));// Nested recursive calls}}intmain(){
       cout <<nestedRecursion(95)<< endl;// Outputs: 105return0;}
    Output
    91
    

    Advantages of Recursion

    • Simplicity and reduced boilerplate code − Recursion helps to simplify solving problems which have a built-in recursive structure, like working with trees or solving combinatorial problems by making it easier to understand and implement.
    • Backtracking − Recursion is a great fit for backtracking algorithms, which involve examining all possible solutions to find one which meets certain criteria.
    • Effective solutions for divide-and-conquer problems − Recursion works perfectly for Divide-and-conquer algorithms, where problems are broken down into smaller sub parts and are solved one by one. This makes problem solving more efficient and easy.

    Recursion Vs. Iteration

    Recursion is a method where a function calls itself over again and again with modified arguments until it reaches its base case which stops the recursion. Whereas, an iteration involves using loops (such as for, while or do-while) where it involves repeatedly executing blocks of code until a certain condition is met.

    Recursion or Iteration: When to Use?

    Recursion

    • The problems which can be divided into similar sub-problems or which have natural recursive patterns such as tree traversal or combinational tasks and manageable depth.
    • When a user needs simple, cleaner and readable code as it provides clean proper arranged code.
    • Examples: Tree and graph traversals, divide-and-conquer algorithms like quicksort and mergesort, and problems involving backtracking like solving mazes or puzzles.

    Iteration

    • Iterative solutions are generally more efficient in terms of memory and execution time and which involves simple repetition.
    • For the problems which require simple looping because iteration is usually more straightforward and efficient.
    • Iteration is more stable for problems which require a large number of repetitions, as it doesn't risk stack overflow.
    • Examples: Looping of Array, Vectors and lists, where require simple mathematical computation and repeated execution of a block of code.

    Comparison between Recursion and Iteration

    RecursionIteration
    Time ComplexityIt can be greater because of its repeated function calls nature.Comparatively less.
    Space ComplexityRecursion often uses more Memory because of the call stack.Uses a fixed amount of Memory.
    Code SizeIn the recursion, the code size is smaller.Comparatively larger code size.
    Execution SpeedThe execution speed is slow when you use recursion.Execution speed is more.

    Limitations of Recursion

    The following are limitations of recursion −

    • Memory Consumption − Each recursive call adds a new frame to the call stack, which can consume a significant amount of memory.
    • Stack Overflow Risk − As recursion relies on call stack to manage function calls, Deep recursion can lead to stack overflow as it exceeds the stack size limit.
    • Performance Overhead − Recursive functions can be less efficient than iterative ones because they involve overhead from multiple function calls and managing the call stack, which can significantly impact performance, especially with deep recursion.
    • Debugging Complexity − Debugging Recursive code can be challenging, especially when dealing with complex recursion or large recursion depths. It needs careful handling of base cases and logic.
    • Space Complexity − Due to the call stack in recursion, it can lead to consuming a lot of memory.
  • Multiple Function Parameters in C++

    C++ multiple function parameters describe the ability of a function to accept more than one argument or can say functions with multiple parameters to perform operations using several inputs, this feature makes a function to execute more complex operations by working with multiple subset of data at once.

    Syntax

    In C++, you can define a function with multiple parameters by listing them in the function’s declaration and definition, separated by commas. Here’s the basic syntax −

    return_type function_name(param1_type param1_name, param2_type parame2_name,...);

    Where,

    param1_type and param1_name are parameter type (eg. int, char, bool, string) and its name respectively, similarly param2_type (eg. int, char, bool, string) and param2_name are parameter type and its name respectively and so on.

    Data Types for Multiple Function Parameters

    There are 2 types of passing data to multiple function parameters, as given in the following −

    1. Single Data Type for Multiple Parameters

    Functions where all parameters are of the same data type.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;// Function taking multiple parameters or arguments of same data type (int)voidsum(int a,int b,int c){
       cout <<"Sum: "<<(a + b + c)<< endl;}intmain(){sum(1,2,3);return0;}
    Output
    Sum: 6
    

    2. Multiple Data Types for Multiple Parameters

    Functions where parameters can have different data types.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;// Function taking arguments of different data typesvoidgetInfo(string name,int age,double height){
       cout << name <<" is "<< age <<" years old and "<< height <<" meters tall."<< endl;}intmain(){getInfo("Aman",26,1.78);getInfo("Naman",32,1.65);return0;}
    Output
    Aman is 26 years old and 1.78 meters tall.
    Naman is 32 years old and 1.65 meters tall.
    

    Explore our latest online courses and learn new skills at your own pace. Enroll and become a certified expert to boost your career.

    Multiple Parameters Passing Techniques

    Multiple parameters (or, single) passing techniques in C++ refer to the methods which are used to pass arguments to functions. These techniques define how the data is transferred and manipulated within the function. Here we will discuss few primary techniques −

    1. Pass by Value

    In pass by value, a copy of the actual parameter’s value is passed to the function. The changes made to the parameter inside the function do not affect the original argument. It is safe and straightforward but can be inefficient for large data structures due to copying.

    2. Pass by Reference

    This method passes a reference to the actual parameter, allowing the function to modify the original argument. The function works with the original data rather than a copy. It is efficient as it avoids copying, but requires careful handling to avoid unintended modifications.

    3. Mutable vs Immutable Types

    Mutable TypesImmutable Types
    These are types whose instances can be modified after they are created.These are types whose instances cannot be changed after they are created.
    Lists, dictionaries, and sets are common mutable types.Integers, strings, and tuples are common immutable types.

    Types of Multiple Function Parameters

    In C++, functions are capable of accepting multiple parameters, and these parameters can be categorized in various ways. Here’s a breakdown for different types of multiple function parameters in C++ −

    1. Fixed Number of Parameters

    A function with a fixed number of parameters where it has a specific and unchanging number of input parameters.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;// Function with a fixed number of argumentsvoidgetDetails(int age,double height,const string& name){
       cout <<"Name: "<< name <<", Age: "<< age <<", Height: "<< height << endl;}intmain(){getDetails(25,5.6,"Sam");return0;}
    Output
    Name: Sam, Age: 25, Height: 5.6
    

    2. Variable Number of Parameters

    A function that can accept a variable number of parameters or arguments. This is typically implemented using variadic functions or template parameter packs.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;// Variadic template functiontemplate<typename... Args>voidprintNumbers(Args... args){(cout <<...<< args)<< endl;}intmain(){printNumbers(1,2,3);// Outputs: 123printNumbers(4,5,6,7,8);// Outputs: 45678return0;}
    Output
    123
    45678
    

    3. Default Parameters

    The default parameters are the parameters with default values that can be omitted when calling the function. The function uses the default values if no arguments are provided for those parameters.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;// Function with default parametersvoidgreet(const string& name ="Guest",int age =0){
       cout <<"Hello, "<< name;if(age >0){
    
      cout &lt;&lt;". You are "&lt;&lt; age &lt;&lt;" years old.";}
    cout << endl;}intmain(){greet();// Outputs: Hello, Guestgreet("Alice");// Outputs: Hello, Alicegreet("Bob",30);// Outputs: Hello, Bob. You are 30 years old.return0;}
    Output
    Hello, Guest
    Hello, Alice
    Hello, Bob. You are 30 years old.
    

    4. Named Parameters (C++ Specific)

    Though C++ does not support named parameters directly, you can achieve similar functionality using a class or struct to encapsulate parameters.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;// Structure to encapsulate parametersstructPerson{
       string name;int age;double height;};// Function that takes a parameter objectvoidprintPerson(const Person& p){
       cout <<"Name: "<< p.name <<", Age: "<< p.age <<", Height: "<< p.height << endl;}intmain(){
       Person alice ={"Alice",25,5.9};printPerson(alice);return0;}
    Output
    Name: Alice, Age: 25, Height: 5.9
    

    5. Parameter Objects

    A single parameter that is a complex type like a class or struct, encapsulating multiple related values.

    Example

    Open Compiler

    #include <iostream>usingnamespace std;// Class to hold multiple parametersclassRectangle{public:int width;int height;Rectangle(int w,int h):width(w),height(h){}};// Function that takes a parameter objectvoidcalculateArea(const Rectangle& rect){
       cout <<"Area: "<<(rect.width * rect.height)<< endl;}intmain(){
       Rectangle rect(10,5);calculateArea(rect);// Outputs: Area: 50return0;}
    Output
    Area: 50
    
  • Functions

    A function is a group of statements that together perform a task. Every C++ program has at least one function, which is main(), and all the most trivial programs can define additional functions.

    You can divide up your code into separate functions. How you divide up your code among different functions is up to you, but logically the division usually is such that each function performs a specific task.

    A function declaration tells the compiler about a function’s name, return type, and parameters. A function definition provides the actual body of the function.

    The C++ standard library provides numerous built-in functions that your program can call. For example, function strcat() to concatenate two strings, function memcpy() to copy one memory location to another location and many more functions.

    A function is known with various names like a method or a sub-routine or a procedure etc.

    Defining a Function

    The general form of a C++ function definition is as follows −

    return_type function_name( parameter list ) {
       body of the function
    }
    

    A C++ function definition consists of a function header and a function body. Here are all the parts of a function −

    • Return Type − A function may return a value. The return_type is the data type of the value the function returns. Some functions perform the desired operations without returning a value. In this case, the return_type is the keyword void.
    • Function Name − This is the actual name of the function. The function name and the parameter list together constitute the function signature.
    • Parameters − A parameter is like a placeholder. When a function is invoked, you pass a value to the parameter. This value is referred to as actual parameter or argument. The parameter list refers to the type, order, and number of the parameters of a function. Parameters are optional; that is, a function may contain no parameters.
    • Function Body − The function body contains a collection of statements that define what the function does.

    Example

    Following is the source code for a function called max(). This function takes two parameters num1 and num2 and return the biggest of both −

    // function returning the max between two numbers
     
    int max(int num1, int num2) {
       // local variable declaration
       int result;
     
       if (num1 > num2)
    
      result = num1;
    else
      result = num2;
    return result; }

    Function Declarations

    A function declaration tells the compiler about a function name and how to call the function. The actual body of the function can be defined separately.

    A function declaration has the following parts −

    return_type function_name( parameter list );
    

    For the above defined function max(), following is the function declaration −

    int max(int num1, int num2);
    

    Parameter names are not important in function declaration only their type is required, so following is also valid declaration −

    int max(int, int);
    

    Function declaration is required when you define a function in one source file and you call that function in another file. In such case, you should declare the function at the top of the file calling the function.

    Calling a Function

    While creating a C++ function, you give a definition of what the function has to do. To use a function, you will have to call or invoke that function.

    When a program calls a function, program control is transferred to the called function. A called function performs defined task and when it’s return statement is executed or when its function-ending closing brace is reached, it returns program control back to the main program.

    To call a function, you simply need to pass the required parameters along with function name, and if function returns a value, then you can store returned value. For example −

    #include <iostream>
    using namespace std;
     
    // function declaration
    int max(int num1, int num2);
     
    int main () {
       // local variable declaration:
       int a = 100;
       int b = 200;
       int ret;
     
       // calling a function to get max value.
       ret = max(a, b);
       cout << "Max value is : " << ret << endl;
     
       return 0;
    }
     
    // function returning the max between two numbers
    int max(int num1, int num2) {
       // local variable declaration
       int result;
     
       if (num1 > num2)
    
      result = num1;
    else
      result = num2;
    return result; }

    I kept max() function along with main() function and compiled the source code. While running final executable, it would produce the following result −

    Max value is : 200
    

    Function Arguments

    If a function is to use arguments, it must declare variables that accept the values of the arguments. These variables are called the formal parameters of the function.

    The formal parameters behave like other local variables inside the function and are created upon entry into the function and destroyed upon exit.

    While calling a function, there are two ways that arguments can be passed to a function −

    Sr.NoCall Type & Description
    1Call by ValueThis method copies the actual value of an argument into the formal parameter of the function. In this case, changes made to the parameter inside the function have no effect on the argument.
    2Call by PointerThis method copies the address of an argument into the formal parameter. Inside the function, the address is used to access the actual argument used in the call. This means that changes made to the parameter affect the argument.
    3Call by ReferenceThis method copies the reference of an argument into the formal parameter. Inside the function, the reference is used to access the actual argument used in the call. This means that changes made to the parameter affect the argument.

    By default, C++ uses call by value to pass arguments. In general, this means that code within a function cannot alter the arguments used to call the function and above mentioned example while calling max() function used the same method.

    Default Values for Parameters

    When you define a function, you can specify a default value for each of the last parameters. This value will be used if the corresponding argument is left blank when calling to the function.

    This is done by using the assignment operator and assigning values for the arguments in the function definition. If a value for that parameter is not passed when the function is called, the default given value is used, but if a value is specified, this default value is ignored and the passed value is used instead. Consider the following example −

    #include <iostream>
    using namespace std;
     
    int sum(int a, int b = 20) {
       int result;
       result = a + b;
      
       return (result);
    }
    int main () {
       // local variable declaration:
       int a = 100;
       int b = 200;
       int result;
     
       // calling a function to add the values.
       result = sum(a, b);
       cout << "Total value is :" << result << endl;
    
       // calling a function again as follows.
       result = sum(a);
       cout << "Total value is :" << result << endl;
     
       return 0;
    }

    When the above code is compiled and executed, it produces the following result −

    Total value is :300
    Total value is :120