Function Overloading in Action, Explained with Code Examples

UPI Study › Courses › C++ Programming › Free lessons › Lesson 8.6 Free with a free account

Function Overloading in Action

C++ Programming · Chapter 8: FunctionsSection 8.6 · lesson 56 of 84video coming soon

← How Arguments TravelNext lesson: Recursive Calls →

Earn 3 college credits for C++ ProgrammingRecommended for credit by NCCRS · Computer Science 242 · self-paced · one payment, lifetime access

In this lesson

One function name, multiple behaviors.

  • State what makes two functions distinct overloads
  • Explain why return type can't distinguish them
  • Follow how the compiler resolves a call
  • Diagnose and fix ambiguity; choose overloads or defaults

Transcript

Everything said in the video, section by section (1,438 words). Read along, or search it.

Opening Question

One Name, Several Functions

C requires every function to have a unique name, which is why its library offers abs, labs, and fabs, for one idea. C++ lets several functions share a name, so long as the compiler can tell the calls apart. This lesson covers exactly what tell apart means, how the choice is made, and what happens when it can't be made at all.

Definition

Signatures Make Overloads Distinct

Two functions may share a name, provided their signatures differ. A signature is the function's name together with the types of its parameters: their number, their types, and the order they appear in. So print can take an int, a double, a string, or an int and a width. The call site then reads naturally. Print 42, print 3.14, print total, and print 42 with 8, all say the same thing about intent. Run it, and the compiler sorts out which function is meant.

Common Mistake

What Counts as a Real Difference

Several things that look like differences aren't. Different parameter types make distinct overloads, and so does a different number of parameters. Same types in a different order also count, because order is part of the signature. But two declarations differing only in parameter names declare the same function twice. Names aren't part of the signature. And const on a by-value parameter changes nothing for the caller, since the function works on its own copy either way. On a reference, though, const is part of the type being referred to, and it does matter to the caller. So an int reference and a const int reference are distinct.

Key Rule

Why Return Type Cannot Distinguish

It seems as though the return type should distinguish overloads. The reason it can't is a matter of what's available at the point of the call. Declaring measure twice, once returning int and once returning double, is an error. The compiler says so. The compiler must choose a function using the call itself, and a call carries arguments. The return value may be assigned, converted, or ignored entirely, as in a bare call to measure. That statement would have no answer. So C++ takes the simpler road. The choice is made from the arguments, and from nothing else.

How It Works

Three Stages of Overload Resolution

Given a call, the compiler works through three stages. Knowing them turns confusing error messages into readable ones. First, the candidates: every visible function with that name. Second, the viable ones: the right number of arguments, each convertible to its parameter. If none are viable, the error is no matching function. Third, the best one, ranked by how little conversion each requires. If two are equally good, the error is ambiguous. Both failures happen while compiling. The ranking, best first: an exact match. Then a promotion, a widening the language treats as natural, such as char to int, or float to double. Then a standard conversion, anything else built in, such as int to double, or anything to bool. And last, a conversion your own types supply. Less work always beats more.

Worked Example

Ranking Calls to Show

Apply the rules to three overloads of show: A takes an int, B a double, and C a char. Show 42 picks A, an exact match. Show 3.5 picks B. And show x, in single quotes, picks C. A float literal picks B, because float promotes to double. And show true picks A, because bool promotes to int. But show 7L, a long, is ambiguous. A long reaches every one of them by a rank-three conversion, so no candidate is better than the rest. The compiler refuses. Ambiguity is an error, never a quiet guess.

Variation

Removing the Char Overload

Take C away and see. With only the int and double versions, show x picks A, the int. Char to int is a promotion, and promotion beats conversion. The program prints A.

Error Analysis

When Two Candidates Tie

An ambiguity error doesn't mean the compiler is being unhelpful. It means two candidates are genuinely equally good, and it won't guess which you meant. Weigh is overloaded for long and for double. Weigh 5 is ambiguous, because int to long and int to double are both rank-three conversions. The error lists both candidates. There are three usual causes. Two candidates each needing a standard conversion of the same rank, as here. Two candidates each matching one argument exactly and converting the other, so neither is better on both. And a default argument making a two-parameter version callable with one argument, so both fit a one-argument call exactly. Try that one: h of 5 is ambiguous too. Equally good means the compiler will not choose for you.

Fixes

Make the Call Exact

Four fixes are available, roughly in order of preference. Make the call exact. Weigh 5.0, or weigh 5L, states which overload is meant, right where the question arises.

More Fixes

Add, Remove, or Rename Overloads

Add the missing overload. If weighing an int is sensible, providing it removes the ambiguity for every such call at once. Remove an overload. Often the two were never meaningfully different. Or give them different names: weigh grams and weigh kilos, if that's what's really going on. When you read the error, the list of candidates is the useful part. Look at what each requires of your argument, and you'll find two conversions of equal rank. No matching function is the opposite problem: nothing was viable at all.

Alternative

Default Arguments Versus Overloading

A default argument gives a parameter a value to use when the caller omits it, so one function can be called several ways. Report can be called with just a title, using a width of 40 and a dot fill. Or with a width of 6, or with a dash fill too. Defaults must be the trailing parameters, and they're stated once, in the declaration. With default arguments, you write one function with one body. That's best when the logic is identical, and some inputs have a sensible fallback. Its risk is a long tail of optional parameters that's hard to read at the call. With overloading, you write several bodies. That's best when behavior genuinely differs by type, or by how many things are supplied. Its risk is ambiguity between convertible types.

Decision Rule

Same Operation or Different Operations

The deciding question is whether the versions do the same thing. Printing with a default width is one operation with a fallback, so a default argument is right. Printing an int and printing a string are two operations that happen to share a name, so overloading is right. And combining the two on the same name invites exactly the ambiguity from the h of 5 example. So do it deliberately, or not at all.

Big Picture

Overloading as Compile-Time Polymorphism

Polymorphism means one name standing for several behaviors. Overloading is one form of it, and the defining feature is when the behavior is chosen. The compiler chooses, while compiling, before the program has ever run, using the written types of the arguments. There's no cost at run time, and the choice can't change while the program runs. That's why the qualifier compile-time is needed. There's a second kind of polymorphism, in which the choice depends on what a value turns out to be while the program is running. It's a different mechanism, with a different cost. Keep the two apart: one is decided by the compiler from written types, the other later, from actual values. A later chapter builds on exactly that.

Guidelines

Using Overloading Well

A few guidelines for using overloading well. Overload only for the same idea. A shared name is a promise that the operations mean the same thing. Draw circle and draw square keep the promise. Process order and process refund may not. Keep behavior consistent: overloads that differ in what they return or in side effects surprise readers, because the call site looks identical. Avoid overloading on freely convertible types. Int, long and double convert into one another readily, which is exactly what produces ambiguity. And prefer clear names over clever ones. If you need a comment to say which overload is which, distinct names were the better design.

Quick Check

Predicting Calls to Tag

Quick check, with a new pair. Tag takes a long, or a double. There's no int version, and no char version. Which one does tag of 2.5f call? And what happens with tag of x, in single quotes? Pause and predict. Tag of 2.5f calls the double version, because float promotes to double. Tag of x doesn't compile. A char promotes only to int, and there's no int version. So long and double are both standard conversions of equal rank, and the call is ambiguous.

Key Takeaways

Overloading Rules in Summary

To summarize. Overloads must differ in their parameter types, number, or order. Return types and parameter names don't count. The compiler prefers an exact match, then a promotion, then a conversion. Two candidates of equal rank are ambiguous, so make the call exact, or redesign the overloads. And when the versions are the same operation with a fallback, use a default argument instead.

About C++ Programming at UPI Study

C++ Programming (Computer Science 242) is a self-paced online course of 84 video lessons in 11 chapters, from your first program to decisions, loops, arrays, functions, classes, files, pointers and inheritance. It carries a NCCRS credit recommendation for 3 semester credits.

Every lesson transcript is free on pages like this one, and the videos are free with a free UPI Study account. Enrolling adds a practice quiz after each lesson, the graded work and final exam that earn the credit, lifetime access, and an official transcript on completion. UPI Study has helped over 130,000 students with college credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Why take it here

Why students take C++ Programming with UPI Study

Your first real programming languageC++ teaches how programs really work: variables, control flow, functions, memory and objects. It is the base for data structures, algorithms, systems and game programming, and for most computer-science degrees.
Credit at a fraction of the priceThe same 3 credits can cost $750 or more at a US college. Here it is one payment, self-paced, with lifetime access.
Finish your degree soonerTransfer credits reduce the courses you still owe, so you can graduate earlier or lighten a heavy semester.
Strengthen an applicationA completed college-level course on an official transcript shows admissions and scholarship committees you can do the work.
Study on your own scheduleNo start dates, no deadlines. Watch the lessons, practice, and take the final when you are ready.
130,000+students helped with college creditsACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Where the credit goes

Universities that work with NCCRS

C++ Programming carries a NCCRS credit recommendation. These universities work with NCCRS; some are UPI Study's signed partners. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Find my college → Not listed? Ask Athena in the corner of this page, or book a 15-minute call.

FAQ

Questions students ask us

About Function Overloading in Action

What makes two C++ functions count as different overloads?
Two functions are distinct overloads when their signatures differ, meaning the name is shared but the number, types, or order of the parameters is different. Parameter names are not part of the signature, so void f(int a) and void f(int b) declare the same function. A const on a by-value parameter does not matter either, but int& and const int& are distinct.
Why can't C++ overload functions based only on return type?
Return type cannot distinguish overloads because the compiler chooses a function using only the arguments in the call. A call's result can be assigned, converted, or ignored, so a bare statement like measure(); gives no hint which version is meant. That is why declaring measure once returning int and once returning double, with the same parameters, is a compile error.
How does the C++ compiler decide which overloaded function to call?
The compiler resolves an overloaded call in three stages: it collects every visible function with that name, keeps the viable ones whose parameters the arguments can convert to, then picks the best match. The ranking runs from exact match, to promotion such as char to int, to standard conversion such as int to double, to user-defined conversion. Given show(int), show(double), and show(char), the call show(3.5) picks the double version.
Why do I get an "ambiguous call" error with overloaded functions, and how do I fix it?
An ambiguous call error means two overloads are equally good matches, so the compiler refuses to guess. For example, with weigh(long) and weigh(double), the call weigh(5) is ambiguous because int to long and int to double are both standard conversions. Fix it by making the call exact, such as weigh(5L) or weigh(5.0), or by adding an int overload, removing one overload, or renaming them.

About the C++ Programming course

How many college credits is C++ Programming?
C++ Programming (Computer Science 242) carries a NCCRS credit recommendation for 3 semester credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
How much does C++ Programming cost and what is included?
$250, paid once, with lifetime access: all 84 video lessons, a practice quiz after each, the graded work and final exam, and an official transcript when you finish. Students who want several courses choose UPI Study PRO instead.
Which universities accept UPI Study credits?
UPI Study has signed partner agreements with universities such as Thomas Edison State University, University of the People and Charter Oak State College, and works with universities such as Penn State, SNHU and SUNY. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities. Use "Find my college" on this page to check yours.
How long does C++ Programming take?
It is self-paced with no deadlines. The 84 lessons total about 0 hours of video; most students add reading and practice time and finish in a few weeks to a few months, on their own schedule.
How are the exams done?
Quizzes and assignments are online in the course. The final exam is taken online with proctoring; a person on the UPI Study team checks assignments, usually within two days.
How do my credits reach my college?
When the course shows 100% complete, request the official transcript from your dashboard. It is sent to the college you name, and you can send it to more than one. Check your college first with "Find my college" on this page, or ask Athena.

Ready for the full course? Earn 3 credits in C++ Programming.

84 video lessons, a quiz after each one, and the graded work that earns the credit. Recommended for credit by NCCRS.

C++ Programming
3 credits · NCCRS
Enroll →