Open In App

Calling of overloaded subroutines and ways for finding accurate match in C++

Last Updated : 29 Dec, 2020
Improve
Improve
Like Article
Like
Save
Share
Report

Just like other subroutines, overloaded subroutines are also called. To decide which function to invoke it is important to determine the number and type of arguments. For example, the below part of code will tell about the calling overloading subroutine:

prnsqr('z')                   // calls #2
prnsqr(13)                    // calls #1
prnsqr(134.520000012)         // calls #4
prnsqr(12.5F)                 // calls #3

The appropriate function is called for execution when the function call initially matches the prototype available along with the digit and type of arguments given.

Between the float, double values, or int or long values, there can be an ambiguity like the function invoked by the following declaration:

void prnsqr(double d);

With a 1.24 value, can assume to be float or double. The constant suffixes(F, U, L, UL), etc. are used to avoid ambiguity these values help in demonstrating which overloading subroutine to be called. The ordinary floating constant (312.32) is a double type, the F suffix (312.32 F) is a float type, L (312.32 L) makes its long double. For integers, a constant without a suffix is the signed int value. U suffix is unsigned constant & L suffix is long, LU or UL is unsigned long. These suffixes can be written in lower or uppercase letters.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <iostream>
using namespace std;
  
class Distance {
private:
    int centimeter;
    int kilometer;
  
public:
    // Default Constructors
    Distance()
    {
        centimeter = 0;
        kilometer = 0;
    }
  
    // Parameterized Constructors
    Distance(int cm, int km)
    {
        centimeter = cm;
        kilometer = km;
    }
  
    // Overload function call
    Distance operator()(int a,
                        int b, int c)
    {
        Distance D;
        D.centimeter = a + c + 10;
        D.kilometer = b + c + 100;
        return D;
    }
  
    // To display distance
    void displayDistance()
    {
        cout << "centimeter: "
             << centimeter
             << "kilometer:"
             << kilometer << '\n';
    }
};
  
// Driver Code
int main()
{
    Distance D1(87, 33), D2;
  
    cout << "First Distance : ";
    D1.displayDistance();
  
    // Invoke operator()
    D2 = D1(10, 10, 10);
    cout << "Second Distance :";
  
    D2.displayDistance();
  
    return 0;
}


Output:

First Distance : centimeter: 87kilometer:33
Second Distance :centimeter: 30kilometer:120

Ways To Find Accurate Match:

The call is resolved for an overloaded subroutine by an instance of function through a process called Argument Matching also termed as the process of disambiguation. Below are the 3 cases that can be possible, the function call may result:

  1. Match: found for function call.
  2. No Match: for function call.
  3. Ambiguous Match: more than one described instance match.

The compiler will try to find the best match for the function call.

Steps Taken By Compiler For Matching

  • Searching for an exact match: When the actual argument type matches exactly with the type of one defined instance, the compiler will invoke for that instance. For Examples:
    // For overloaded functions
    void afunc(int);
    void afunc(double);    
    
    // For exact match. Match afunc(int)
    afunc(0);
    

    0(zero) is int type, matches afunc(int) with call.

    Below is the program for the same:

    C++




    // C++ program for the above approach
      
    #include <iostream>
    using namespace std;
      
    // Function for integer parameter
    void afunc(int h)
    {
        cout << "Integer:" << h;
    }
      
    // Function for double parameter
    void afunc(double d)
    {
        cout << "double:" << d;
    }
      
    // Driver code
    int main()
    {
        afunc(0);
        return 0;
    }

    
    

    Output:

    Integer:0
    
  • Match through promotion: The compiler will make an attempt to get a match through the promotion of the actual argument if no exact match found. If all values cannot be represented by int and the conversion of integer types into (char, short, enumerator, int), or to unsigned int is called integral promotion. Now we will see the following code part:

    void afunc(int)
    void afunc(float)

    // For match through promotion
    afunc(‘c’)

    where, ‘c’ is the type char and promoted to INT type as no exact match found.

    Below is the program for the same:

    C++




    // C++ program for the above approach
    #include <iostream>
    using namespace std;
      
    // Function for integer parameter
    void value(int s)
    {
        cout << "Integer:" << s;
    }
      
    // Function for character parameter
    void value(char* b)
    {
        cout << "Char:" << b;
    }
      
    // Driver Code
    int main()
    {
        char st = 'd';
        value(st);
        return 0;
    }

    
    

    Output:

    Integer:100
    
  • Through the application of the standard C++ conversion rule found a match: An attempt is made to achieve a match through a standard conversion of the actual argument if no exact match or match through a promotion is found. Below is the example for the same:

    void afunc(char)
    void afunc(double)

    // For match through std conversion
    afunc(471)
    match a func(double)

    Using C++ standard conversion rules the int argument 471 can be converted to a double value 471 and if the actual argument may be converted to multiple formal argument types compiler will generate an error message as it is an ambiguous match. For Example:

    void afunc(long)
    void afunc(double)
    
    // Error will generate as ambiguous match
    afunc(15)
    

    The int argument 15 converted to long or double generating an ambiguous circumstance as to which afunc() be used.

    Below is the program for the same:

    C++




    // C++ program to explain the standard
    // conversion rule
    #include <iostream>
    using namespace std;
      
    // Driver Code
    int main()
    {
        // integer h
        int h = 11;
      
        // character c
        char s = 'a';
      
        // s implicitly converted
        // to int. ASCII value of
        // 'a' is 97
        h = h + s;
      
        // h is implicitly converted
        // to float
        float f = h + 1.0;
      
        cout << "h = " << h << endl
             << "s = " << s << endl
             << "f = " << f << endl;
      
        return 0;
    }

    
    

    Output:

    h = 108
    s = a
    f = 109
    

    Note: If no promotion is seen then the compiler finds a match through standard conversion. Any numeric type is matched with another numeric type including unsigned (say int and float). Enum is going to match with the formal type of numeric type ( e.g. enum to float). 0 has to be matched a pointer type and numeric type (say 0 to char*, 0 to float). Though Pointer matched by a void pointer.

  • Through the application of a user define conversion find a match: Now the compiler will use a user-defined conversion in combination with integral promotion and built-in conversions to find a unique match if all the above steps will fail. Any function whether it is a class member or just a normal function can be overloaded in C++ given is needed to work for different argument types numbers and combinations.

    Below is the program for the same:

    C++




    // C++ program to illustrate the user
    // defined type casting
    #include <iostream>
    using namespace std;
      
    // Driver Code
    int main()
    {
        double h = 1.4;
      
        // Explicit conversion
        // from double to int
        int add = (int)h + 2;
      
        cout << "Add = " << add;
        return 0;
    }

    
    

    Output:

    Add = 3
    


Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads