Language Selector

7.6 — Function overloading

Function overloading is a feature of C++ that allows us to create multiple functions with the same name, so long as they have different parameters. Consider the following function:

This trivial function adds two integers. However, what if we also need to add two floating point numbers? This function is not at all suitable, as any floating point parameters would be converted to integers, causing the floating point arguments to lose their fractional values.

One way to work around this issue is to define multiple functions with slightly different names:

However, for best effect, this requires that you define a consistent naming standard, remember the name of all the different flavors of the function, and call the correct one (calling AddD() with integer parameters may produce the wrong result due to precision issues).

Function overloading provides a better solution. Using function overloading, we can declare another Add() function that takes double parameters:

We now have two version of Add():

Which version of Add() gets called depends on the arguments used in the call -- if we provide two ints, C++ will know we mean to call Add(int, int). If we provide two floating point numbers, C++ will know we mean to call Add(double, double). In fact, we can define as many overloaded Add() functions as we want, so long as each Add() function has unique parameters.

Consequently, it’s also possible to define Add() functions with a differing number of parameters:

Even though this Add() function has 3 parameters instead of 2, because the parameters are different than any other version of Add(), this is valid.

Note that the function’s return type is NOT considered when overloading functions. Consider the case where you want to write a function that returns a random number, but you need a version that will return an int, and another version that will return a double. You might be tempted to do this:

But the compiler will flag this as an error. These two functions have the same parameters (none), and consequently, the second GetRandomValue() will be treated as an erroneous redeclaration of the first. Consequently, these functions will need to be given different names.

Also keep in mind that declaring a typedef does not introduce a new type -- consequently, the following the two declarations of Print() are considered identical:

How function calls are matched with overloaded functions

Making a call to an overloaded function results in one of three possible outcomes:

1) A match is found. The call is resolved to a particular overloaded function.
2) No match is found. The arguments can not be matched to any overloaded function.
3) An ambiguous match is found. The arguments matched more than one overloaded function.

When an overloaded function is called, C++ goes through the following process to determine which version of the function will be called:

1) First, C++ tries to find an exact match. This is the case where the actual argument exactly matches the parameter type of one of the overloaded functions. For example:

Although 0 could technically match Print(char*), it exactly matches Print(int). Thus Print(int) is the best match available.

2) If no exact match is found, C++ tries to find a match through promotion. In the lesson on type conversion and casting, we covered how certain types can be automatically promoted via internal type conversion to other types. To summarize,

  • Char, unsigned char, and short is promoted to an int.
  • Unsigned short can be promoted to int or unsigned int, depending on the size of an int
  • Float is promoted to double
  • Enum is promoted to int

For example:

In this case, because there is no Print(char), the char ‘a’ is promoted to an integer, which then matches Print(int).

3) If no promotion is found, C++ tries to find a match through standard conversion. Standard conversions include:

  • Any numeric type will match any other numeric type, including unsigned (eg. int to float)
  • Enum will match the formal type of a numeric type (eg. enum to float)
  • Zero will match a pointer type and numeric type (eg. 0 to char*, or 0 to float)
  • A pointer will match a void pointer

For example:

In this case, because there is no Print(char), and no Print(int), the ‘a’ is converted to a float and matched with Print(float).

Note that all standard conversions are considered equal. No standard conversion is considered better than any of the others.

4) Finally, C++ tries to find a match through user-defined conversion. Although we have not covered classes yet, classes (which are similar to structs) can define conversions to other types that can be implicitly applied to objects of that class. For example, we might define a class X and a user-defined conversion to int.

Although cValue is of type class X, because this particular class has a user-defined conversion to int, the function call Print(cValue) will resolve to the Print(int) version of the function.

We will cover the details on how to do user-defined conversions of classes when we cover classes.

Ambiguous matches

If every overloaded function has to have unique parameters, how is it possible that a call could result in more than one match? Because all standard conversions are considered equal, and all user-defined conversions are considered equal, if a function call matches multiple candidates via standard conversion or user-defined conversion, an ambiguous match will result. For example:

In the case of Print('a'), C++ can not find an exact match. It tries promoting ‘a’ to an int, but there is no Print(int) either. Using a standard conversion, it can convert ‘a’ to both an unsigned int and a floating point value. Because all standard conversions are considered equal, this is an ambiguous match.

Print(0) is similar. 0 is an int, and there is no Print(int). It matches both calls via standard conversion.

Print(3.14159) might be a little surprising, as most programmers would assume it matches Print(float). But remember that all literal floating point values are doubles unless they have the ‘f’ suffix. 3.14159 is a double, and there is no Print(double). Consequently, it matches both calls via standard conversion.

Ambiguous matches are considered a compile-time error. Consequently, an ambiguous match needs to be disambiguated before your program will compile. There are two ways to resolve ambiguous matches:

1) Often, the best way is simply to define a new overloaded function that takes parameters of exactly the type you are trying to call the function with. Then C++ will be able to find an exact match for the function call.

2) Alternatively, explicitly cast the ambiguous parameter(s) to the type of the function you want to call. For example, to have Print(0) call the Print(unsigned int), you would do this:

Multiple arguments

If there are multiple arguments, C++ applies the matching rules to each argument in turn. The function chosen is the one for which each argument matches at least as well as all the other functions, with at least one argument matching better than all the other functions. In other words, the function chosen must provide a better match than all the other candidate functions for at least one parameter, and no worse for all of the other parameters.

In the case that such a function is found, it is clearly and unambiguously the best choice. If no such function can be found, the call will be considered ambiguous (or a non-match).


Function overloading can lower a programs complexity significantly while introducing very little additional risk. Although this particular lesson is long and may seem somewhat complex (particularly the matching rules), in reality function overloading typically works transparently and without any issues. The compiler will flag all ambiguous cases, and they can generally be easily resolved.

7.7 -- Default parameters
7.5 -- Inline functions

47 comments to 7.6 — Function overloading

  • this is very good site for c++.

  • Aaron

    “In this case, because there is no Print(char), the char ‘a’ is promoted to an integer, which then matches Print(int).”

    There is a Print(char) though!!

    • No there isn’t. :) There’s a Print(int) and a Print(char*). Print(char*) is not the same thing as Print(char). Print(char) would be used for single character. Print(char*) would be used to print C-style character strings.

      • Aaron

        Oh yea forgot about the * affecting the way it is evaluated. Good tutorials by the way. :)

      • weirdolino

        Minor issue but if it prints C-style character strings, shouldn’t the the parameter be called szValue according to Hungarian Notation? Like void Print(char *szValue); ?

        • Yes, and I’m horrible about following that rule. I’m sure I’ve screwed it up in other tutorials as well. Good observation, by the way. I fixed it up for this tutorial at least.

  • Tom

    Hello Alex -

    Another small typo:

    “Consequently, an ambiguous match needs to be disambiguated before your program will compiler.”

    Also, it would help if there were more quiz questions and exercises to reinforce the material - there is a lot here to remember.


    • Thanks for the note. As you’ve noticed, the number of quiz questions and exercises falls off significantly as you go through the tutorials. The reason for this is simple: they take a long time to write, especially as we get into more complex subjects.

      Given a limited amount of time to work on this site, I decided there was more benefit to spending my time writing subject tutorials than quiz questions. Once the tutorials are done (which actually isn’t that far off now), I do intend to go back and add more quiz questions and exercises.

      • cpplx

        i was just thinking how my learnig degraded since im a "learn by doing" type.

        • Alex

          Because there aren’t as many quiz questions in the later lessons? I’m working to fix that but I haven’t gotten this far yet. :(

          • cpplx

            i lack any practice. i will soon forget how to write a helloworld.
            i understand it does not happen in a snap and just letting you know how usefull(or not) your site is(the further i read. im at 7.13 atm).

          • Pablo

            I agree with Tom and ccplx, but it is great knowing you have this in mind! I will stay alert for future updates.

            Good work!

            PS: I also agree this material would make a successful book, specially given that the website is quite well known by now!

  • Vishnu Prasad.H

    i did not understand the meaning of

    typedef is a keyword to give a new name to a data type right?
    so which datatype gets the new name here ? and what is it?
    will *string be th enew name for char? or *string be a pointer to a char ?
    then how come typedef serves it purpose?
    some body plzzzz explain..

    • It was somewhat ambiguously worded, so I rewrote the sentence just before that example.

      Typedef lets you give a new name to an existing type.

      typedef char *string means we’re giving the new name “string” to the type “char *”

      Consequently, the following are identical:

      There is more information in the lesson on typedefs

      • bla

        Got stuck at this too 😉

        Wouldn’t this look clearer if you typed:

        • Eiq

          Many people type:
          char* a;
          But I think this could lead to confusion:
          char* a,b;
          Are there two pointers to char ? No, actually there is one pointer a and one integer b. So this:
          char *a,*b;
          seems quite clear. But what about this:
          char* a, * b;
          or even
          char* a, *b;

  • Gareth37

    i dont understand what is the type "char *" ?

    i have seen a different example from c code such as -

    char *animal = "dog"; //This creates a pointer (called animal) to the string "dog".

    so if we had -
    typedef char *string;

    then could we have
    string animal = "dog";

    this would be the same as
    char *animal = "dog";

    [ Yes. - Alex ]

    is the above true because a pointer is the same as an array so
    char *animal = "dog";

    is really the same as
    char animal[] = "dog";

    which after the typdef -
    typdef char *string;

    means this is now also the same -
    string animal = "dog";

    [ Yes, however, a pointer is not the same thing as an array. Arrays in C++ are implemented using pointers. But it is possible (and common) to have pointers that point to things that are not arrays at all. - Alex ]

  • manu

    Alex can you please explain what is abstraction and how we can implement in our project and how it is different from encapsulation?.data hiding is abstraction or encapsulation?.

  • TomarBueno

    This is a excellent side to get answer clear neat…….

  • Gammerz

    In your above example, I don’t understand the syntax of the struct declaration. In section 4.7 (Structs), your function declarations don’t contain the keyword “struct”, “Employee” is a struct:-

    Is this a new way of defining a prototype that I don’t believe I’ve come across in your tutorials?

  • smitha

    Can functions be overloaded on the basis of one of the arguments being a pointer?

    The compiler doesnt throw an error , so I presume that it is valid, but what I dont understand is that essentially both the arguments are of type int.(even if one contains an address). Kindly explain

  • smitha

    “If there are multiple arguments, C++ applies the matching rules to each argument in turn. ”

    if this is true, then why does the compiler report an ambigous call for the following code:

  • Above it says:

    There are two ways to resolve ambiguous matches:

    1) Define a new overloaded function that takes parameters of exactly the type you are trying to call the function with.

    2) Explicitly cast the ambiguous parameter(s) to the type of the function you want to call.

    I would propose a third way:

    3) Simply give each and every function a unique name.

    In other words, avoid problems with overloading by not using overloading. At least as long as you don’t see considerate advantages with using overloading.

    PS: Though I’m rather good at PHP, that reminds of C++, I’m a C++ beginner and have never used overloading. Please correct me if you have more experience of C++ than I have and disagree with the piece of advice above.

    • smitha

      Not that am an expert in C++ but overloading is one of the key concepts of C++ through which it implements polymorphism. The advantage is in terms of usability of a function .

      The classic textbook example would be a call a function Area() to find the area of different shapes depending on the number of parameters.
      Overloading would basically be used when you need to do the same thing in different ways. for example finding the area of a rectangle is different from finding the area of a circle.
      Area(int l, int b);
      Area(int r);

      So here the decision as to which function should be executed goes automatically to the compiler and not to the programmer and thereby reducing the number of if-else statements.

    • Vivek

      Overloading is very useful, especially for class constructors.

    • Eiq

      As smitha said, consider several classes that are derived from some base class (triangle, circle and square from object). Now you put thousands of them into vector and want to find their combined area. So you would probably run through some for cycle.
      With overloading you just call area() member function for each one of them. Without overloading you would have to find out what class is the current class and then call appropriate function.

  • Matt

    This really confuses me here.

    typedef char *string;
    void Print(string szValue);
    void Print(char *szValue);

    What exactly does the asterisk do in this situation? The closest thing I can relate it to is the pointer stuff but it’s not pointing to any address here. I tried reviewing the previous lessons again but I still don’t get it.

  • Jyoti

    Hi Alex..
    I have heard that “Avoid overloading function where one takes integral type argument and other takes pointer”
    What could be the reason?


  • developer

    i was expecting name mangling here

  • shini

    what are the rules to be followed in function overloading?

  • Aparna

    Can you please explain this part better. I don't undertstand it.

    typedef char *string;  // what does this typedef do exactly?
    void Print(string szValue);
    void Print(char *szValue); // this bit would be void Print(*string *szValue) and this makes no sense


  • shiva

    Hi alex,

    [ void add (int a, int b);
      Void add (int a, int b, int c=0);]
    Which function gets called when add (5,10); is called

  • I encountered a really strange thing! ~ Look at the following code:

    When compiling this program compiler give me an error:
    error: call of overloaded ‘add(double, double)’ is ambiguous
    and when I changed ‘float’ to ‘double’ everything went OK!
    Except both ‘float’ and ‘double’ aren’t floating point number?
    so why we have an compiler error here?

  • Kevin

    Is this a mistake?

  • Kevin

    If you could add tiny quizzes at the end of each lesson, that would greatly help with memory retention in my opinion. I’m not talking writing code, but I mean something like… asking the reader to get some paper and write the terms defined within that particular lesson from memory to see if they fully understand it. Yeah, people will cheat… but this is all self taught anyways. The only person losing in that case is them.

    I can understand if you don’t have time, but with tiny quizzes like this you could pretty much pass it off to anyone, since the only effort involved is writing a few sentences at the end of each, asking the reader what ambiguous matches are, or asking what an enum will be promoted to (for example).

Leave a Comment




six − two =

Put C++ code inside [code][/code] tags to use the syntax highlighter