A single function name can have multiple declarations. If
those declarations specify different function signatures, the function
name is overloaded. A function call to an
overloaded function requires the compiler to resolve the overloaded name
and decide which function to call. The compiler uses the argument types
(but not the return type) to resolve calls to overloaded functions. Example 5-11 shows simple examples
of two overloaded functions named sqrt
: one for int
arguments and the other for double
arguments. The rest of this section
explains the rules for overloading and resolution.
Example 5-11. Overloaded functions
int sqrt(int); double sqrt(double); int main( ) { std::cout << sqrt(3) << '\n'; // sqrt(int) std::cout << sqrt(3.14) << '\n'; // sqrt(double) }
Whenever you declare more than one function with the same name in the same scope, you are overloading the function name. The function can be an ordinary function, member function, constructor, or overloaded operator.
Overloaded functions must differ in their parameter lists: they must have a different number of parameters, or the parameter types must be different. Refer to Section 5.2.2 earlier in this chapter for information on equivalent parameter types.
Default arguments are not considered when declaring overloaded
functions (but are important when resolving a call to an overloaded
function, as described in Section 5.3.2). Example 5-12 shows overloaded
constructors and member functions for the point
class, and overloaded declarations for
the add
function.
Example 5-12. Overloaded constructors, member functions, and function declarations
class point { public: point(int x = 0); // Overloaded constructors point(int x, int y); point(const point& pt); // x and y are overloaded. int x( ) const { return x_; } void x(int newx) { x_ = newx; } int y( ) const { return y_; } void y(int newy) { y_ = newy; } private: int x_, y_; }; // add is overloaded. int add(int, int); int add(int); double add(double, double); double add(double); long add(long, long); long add(long); // The following declarations are not overloaded, but are redeclarations of the // add functions. int add(int a = 0, int b = 0); long add(signed long, long signed); long add(int, int); // Error: cannot overload on return type
A function call expression (Chapter 3) must identify the function
being called, based on its name and arguments. For example, the simple
expression f(x)
might be a call to
a function named f
, a function call
through a function pointer named f
,
a function template named f
, the
construction of an object of class f
, a conversion of x
to a type named f
, or the invocation of the function call
operator of an object named f
. In
each situation, the compiler might use different rules for
interpreting f
and x
.
The compiler first uses the function name and context to create a list of candidate functions. The number and types of the arguments are used to select the best match from the candidates, and that function is the one that is called. If no match is found, the compiler reports an error. If more than one match ties for "best," the compiler reports an ambiguity error.
For example, the C++ standard library declares three different
sqrt
functions (see <cmath>
in Chapter 13):
float sqrt(float); double sqrt(double); long double sqrt(long double);
Suppose you add another function named sqrt
, such as the following, to apply it to
each element of an array :
void sqrt(const double data[], size_t count);
In a function call to sqrt
(e.g., sqrt(x)
), the compiler first
uses the ordinary rules of name lookup (Chapter 2) to find the first suitable
object or function named sqrt
.
Suppose you used using
namespace
std;
to import the standard sqrt
functions into the same namespace as
your sqrt
function. The compiler
would collect all the overloaded sqrt
functions as the candidate list, which
has four elements in this case (the three original functions plus the
array version). The list is then pruned to eliminate functions with
the wrong number of arguments. In this case, the array version of the
function is eliminated because the expression has only one argument.
Finally, the type of x
is used to
determine which function to call. If there is an exact match, the
corresponding function is called. If x
is, for example, an integer, the compiler
reports an error because the three floating-point sqrt
functions look equally good. If
x
has class type, and the class has
a conversion function to one of the floating-point types, the compiler
implicitly calls that conversion and then calls the corresponding
function:
struct FixedPoint { ... operator long double( ); }; void demo( ) { FixedPoint x; std::cout << sqrt(x) << '\n'; // Prints a long double }
If a candidate is a function template, the compiler deduces the argument types (see Chapter 7), and from that point on, the template instance is treated as a normal function.
The rules for creating the candidate list and argument list
depend on the context of the function call. The argument list can also
depend on context: when choosing an overloaded function to call, a
member function's class is treated as an argument type. More
precisely, member functions have an implicit
object
parameter whose type is a reference to
T
, in which T
is
the class that defines the member function. Any qualifiers on the
member function also qualify the type (that is, the object type for a
const
function is const
T
&
). In the function body, the type of
this
is a pointer to qualified
T
. (See Chapter 6 for more information about
this
.)
A call to a member function applies to a specific object,
which is the implicit object
argument. When calling a member function with the
->
or . operator, the implicit
object argument is the left operand. For an overloaded binary operator
(such as operator<<
), the
implicit object argument is the left operand. For a unary operator,
the implicit object argument is the operand. When calling an
unqualified function inside a nonstatic member function, the implicit
object argument is *this
. The
implicit object argument is considered the first argument in the
argument list. Unlike normal arguments, implicit type conversions do
not take place for the implicit object argument.
This section describes how the compiler creates its list of candidate functions. Table 5-1 summarizes the various categories of function calls, and the subsequent subsections provide the details.
Table 5-1. Function calls and candidate lists
An expression that uses the . or ->
operator to call a function must
call a member function. The function name is looked up in the class
of the left operand and in its base classes (using the name lookup
rules listed in Chapter 2). The
search starts in the most-derived class. If that class declares a
member function with the desired name, the search stops, and the
candidate functions are all the member functions with the same name
in that class. If no matching member function is found, the search
continues with the immediate base classes. The search stops when a
matching name is found.
In other words, a derived class cannot overload a function that is
declared in a base class. Instead, if the derived class has a
function with the same name, the derived class hides the name that
would be inherited from the base class (or the derived class might
override a virtual function; see Chapter 6). Insert a using
declaration in the derived class if
you want the compiler to consider the base class functions as
candidates, as shown in Example
5-13.
Example 5-13. Overloading inherited functions
#include <iostream> #include <ostream> class base { public: void f(int) { std::cout << "f(int)\n"; } void g(int) { std::cout << "g(int)\n"; } }; class derived : public base { public: void f(double) { std::cout << "f(double)\n"; } void g(double) { std::cout << "g(double)\n"; } using base::g; // g(int) and g(double) are visible. }; int main( ) { derived d;d.f(3);
// Calls derived::f(double)d.g(42);
// Calls base::g(int) }
If a class has multiple immediate base classes, overload resolution must find a name in
only one of the base classes. If functions with the desired name are
found in multiple immediate base classes, the compiler reports an
ambiguity error. To resolve this ambiguity, use the scope operator
(:
:) to qualify the function name
in the derived class, as shown in Example 5-14.
Example 5-14. Avoiding ambiguous base-class overloads
struct base1 { void func(int); }; struct base2 { void func(double); }; struct derived : base1, base2 { // Call to overloaded func is ambiguous. void demo1(long x) { func(x); } // Qualify the name to resolve ambiguity. void demo2(long x) { base2::func(x); } };
An ordinary-looking function call can be a nonmember function, a member function, an object of class type, a type name, or a variable of type pointer-to-function. For a variable of type pointer-to-function, overload resolution takes place when a value is assigned to the variable (discussed later in this chapter). In the other cases, the usual name lookup rules apply when finding the candidate functions.
A function call in a member function searches first for matching member functions in the same class or an ancestor class. The search for a match begins in the class that is declaring the member function. If a match is found, candidate functions are taken from that class. If no matches are found, the search continues with ancestor classes, following the same rules as for qualified member function calls. If no matches are found in any ancestor classes, the namespace of the class is searched for nonmember functions. Example 5-15 shows how a matching member function in a base class precludes finding a better match in the global namespace.
Example 5-15. Finding candidate member functions
#include <iostream>
#include <ostream>
void proc(int x)
{
std::cout << "proc(int:" << x << ")\n";
}
class base {
public:
void f(int) { std::cout << "f(int)\n"; }
void g(int) { std::cout << "g(int)\n"; }
void proc(double) { std::cout << "base::proc(double)\n"; }
};
class derived : public base {
public:
void f(double) { std::cout << "f(double)\n"; }
void g(double x) {
std::cout << "g(double)\n";
proc(42); // Calls base::proc(double), not ::proc(int)
}
using base::g;
};
// Declared after derived, so call to proc( ) inside g( ) never sees this proc( ).
void proc(double x)
{
std::cout << "proc(double:" << x << ")\n";
}
int main( )
{
derived d;d.g(3.14159);
// Calls g(double)
}
If a function call expression resolves to an object of class type, the class must have a function call operator or a conversion operator, in which the conversion is to a function type: pointer-to-function, reference-to-function, or reference-to-pointer-to function.
A conversion operator is rarely used. The compiler constructs a wrapper function so that the conversion function is the first argument. The conversion type followed by the types of the actual arguments is the new list of argument types to use in overload resolution. In other words, all of a class's function-type conversion operators participate in overload resolution.
Example 5-16 shows how a class-type object is used as the left operand of a function call.
Example 5-16. Calling a class-type object as a function
#include <iostream> #include <ostream> typedef void (*strproc)(const char*); void print(const char* str) { std::cout << "const char*:" << str << '\n'; } void print(int x) { std::cout << "int:" << x << '\n'; } void print(double x) { std::cout << "double:" << x << '\n'; } struct simple { void operator( )(int x) { print(x); } // print(int) void operator( )(double x) { print(x); } // print(double) }; typedef void (*intfunc)(int); typedef void (*dblfunc)(double); struct indirect { operator intfunc( ) { return print; } // print(int) operator dblfunc( ) { return print; } // print(double) operator strproc( ) { return print; } // print(const char*) }; int main( ) { simple sim; indirect ind;sim(42);
// Prints "int:42"sim.operator( )(42);
// Prints "int:42"sim(42.0);
// Prints "double:42"ind(42);
// Prints "int:42"ind.operator intfunc( )(42);
// Prints "int:42"ind(42.0);
// Prints "double:42"ind("forty-two");
// Prints "const char*:forty-two" }
The function for an overloaded operator is chosen according to the usual rules for resolving overloaded functions, in which the operator's operands are the function's arguments. You can overload operators only if at least one operand has a user-defined type. If all operands have built-in types, an operator has its built-in meaning.
If the left operand of an operator has class type, the
operator can be a nonstatic member function or a nonmember function.
Otherwise, the function must be a nonmember function. The operator
function name is formed from the keyword operator
followed by the operator symbol,
e.g., operator[]
, operator++
, or operator-
. Unary operators can be member
functions with no arguments or nonmember functions of one argument.
Binary operators are member functions of one argument or nonmember
functions of two arguments. Postfix increment and decrement
operators are different. They are implemented as binary operators
for which the right operand is an int
. (See Chapter 3 for more
information.)
The ->
operator is also
different. Although it is a binary operator, it is treated as a
unary operator. It must be implemented as a member function, so the
function takes no arguments. It returns a pointer or another object
that overloads the ->
operator. Ultimately, the overloaded operators must resolve to a
pointer of class type, to which the built-in ->
operator can be applied.
The candidate functions for the overloaded operator include all member, nonmember, and built-in candidate functions. Member functions do not take precedence over nonmember functions.
Example 5-17 shows how operator functions are different from named functions. In particular, it shows how operators are resolved by considering member functions and global functions, whereas named member functions take precedence over named global functions.
Example 5-17. Calling overloaded operators
class demo { public: demo(int v) : value_(v) {} demo add(const demo& d) const; demo sub(const demo& d) const; demo mul(const demo& d) const; demo operator+(const demo& d) const; demo operator-(const demo& d) const; demo operator*(const demo& d) const; operator int( ) const { return value_; } private: int value_; }; // Silly examples, but illustrative demo add(const demo& a) { return a; } demo mul(const demo& a) { return a; } demo div(const demo& a) { return a; } demo operator+(const demo& a, const demo& b) { return a.operator+(b); // Force use of member function. } demo demo::add(const demo& d) const {return *this + d;
// Error: calls ::operator+( ) or demo::operator+( )? } demo demo::sub(const demo& d) const {return this->operator-(d);
// Member operator } demo demo::mul(const demo& d) const {return ::operator*(*this, d);
// Global operator } demo demo::operator+(const demo& d) const { return demo(int(*this) + int(d)); } demo demo::operator-(const demo& d) const { return sub(d); // Calls demo::sub (recurses infinitely) } demo demo::operator*(const demo& d) const { return ::mul(d); // Scopes operator to call global mul( ) }
An object can be initialized using function-like syntax (see Chapter 2). When an object of class type is so initialized, the candidate functions are constructors of the named class. The same syntax applies to conversion initialization covered later in this chapter. Example 5-18 shows function-like initializers that call an overloaded constructor.
An object can be initialized using assignment-like syntax (see
Chapter 2). The candidate
functions for "T
x
=
i
" are single-argument,
non-explicit
constructors of
T
. If i
has class type, the candidates are
conversion functions that convert i
to type T
, as shown in Example 5-19. The compiler is
free to call T
's copy constructor
to copy a temporary T
object to
x
. Even if the compiler optimizes
away this extra copy, T
must have
an accessible copy constructor.
Example 5-19. Resolving assignment-like initialization
class point { public: point( ) : x_(0), y_(0) {} point(int x) : x_(x), y_(0) {} point(int x, int y) : x_(x), y_(y) {} int x( ) const { return x_; } int y( ) const { return y_; } private: int x_, y_; }; class dot { public: dot(int x, int y) : center_(point(x, y)) {} dot(const point& center) : center_(center) {} operator point( ) const { return center_; } private: point center_; };point p1 = 3;
// Invokes point(int) constructorpoint p2 = 4.2;
// Converts 4.2 to 4, and invokes point(int)dot d1 = p1;
// Invokes dot(const point&) constructorpoint p3 = d1;
// Invokes dot::operator point( ) and implicit // point(const point&) copy constructor
An object that does not have class type can be initialized
with an object of class type. The candidate functions are the
conversion functions of that class type. Example 5-20 shows two cases of
conversion initialization. In the first, the object c
is initialized with an rbnode<int>
object, n
, and the compiler calls operator
color(
)
. The second invokes operator
T(
)
, in which T
is
int
, to initialize i
to the value 42
.
Similar to initializing an object of non-class type with an
expression of class type, you can initialize a reference to an
lvalue that results from a conversion function and initialize a
const
reference to an rvalue.
Most conversion operators do not return lvalues, so the const
reference version of this rule is
used more often. Example
5-21 shows some examples of binding references to conversions. The object c1
is bound to a temporary copy of
n.color_
, and i1
is bound directly to n.value_
.
Example 5-21. Binding references to conversion lvalues
enum color { red, black };
template<typename T>
class rbnode {
public:
rbnode(const T& value, color c);
operator color( ) { return color_; }
operator T&( ) { return value_; }
private:
T value_;
color color_;
};
rbnode<int> n(42, black);const color& c1 = n;
int& i1 = n;
When taking the address of a function, the compiler does not have the benefit of an argument list to help resolve overloading. Instead, it collects a list of candidate functions and picks one based on the type required by the context. The context can be an initializer, an assignment, a function argument, the return value of a function, or an explicit type cast.
Of the potentially matching functions, nontemplate functions are better than template functions, and more-specific template functions are better than less-specific template functions. There must be exactly one best function, or else the compiler reports an error. Example 5-22 shows simple examples of resolving the addresses of overloaded functions.
Example 5-22. Taking the address of an overloaded function
int abs(int); long abs(long); double abs(double); template<typename T> T abs(T x); template<typename T, typename U> T abs(T x, U = U( )); int main( ) { int (*intfunc)(int) = &abs; // abs(int) double (*dblfunc)(double) = &abs; // abs(double) float (*fltfunc)(float) = &abs; // abs<float> short (*shrtfunc1)(short, int) = &abs; // abs<short,int> short (*shrtfunc2)(short) = &abs; // abs<short> }
Once the compiler has found the list of candidate functions, it must choose the "best" match from the list. The candidate list is first pruned by removing functions with the wrong number of arguments. Then the remaining functions are checked to determine how to convert the actual arguments to the desired parameter types. The function with the simplest conversions wins. This section discusses these two steps.
Once the compiler has assembled its list of candidate
functions, it prunes the list by removing functions that have the
wrong number of arguments. If the function call has n
argument expressions, a function is
kept in the list if any of the following apply:
It has exactly n
parameters.
It has fewer than n
parameters followed by an ellipsis parameter.
It has more than n
parameters, and the extra parameters have default
arguments.
Also, each actual argument must be convertible (applying the rules described in the next section) to the parameter type.
Of the remaining candidate functions, the "best" function is the one that is called. If multiple functions are tied for best, the compiler reports an error. The best function is found by comparing the implicit type conversion sequences needed for each argument type (and possibly an implicit object argument). As described in the next section, some sequences are better than others. When comparing two functions, the better function is the one with the better conversion sequences:
If two functions A and B have argument conversion sequences that are equally good, but A has at least one argument with a better sequence, A is the better function.
If all the argument conversion sequences are equally good, a nontemplate function is better than a template function.
If the conversion sequences for two template functions are equally good, a more-specific template function is better than a less-specific template function.
An actual argument is implicitly converted to the desired parameter type by undergoing a series of transformations. Basically, a better conversion is one in which the argument type is closer to the parameter type and, therefore, the type undergoes fewer transformations.
A standard conversion sequence is a sequence of built-in transformations that are based on automatic type conversions (Chapter 3). A sequence is built from at most one of each of three kinds of transformations. The quality of a standard conversion sequence is dictated by its worst transformation, in which the value-preserving transformations are better than those that might discard information. The transformations are as follows, ordered from best to worst:
An lvalue transformation is the conversion of an array to a pointer, an lvalue
to an rvalue, or a function to a function pointer. A
qualification adjustment is adding const
or volatile
qualifiers to match the
parameter. These transformations are just as good as no
transformation at all:
void func1(const int& x); void func2(const char* str); func1(42); func2("Hello");
The built-in type promotions are listed in Chapter 3. In general, type promotions are from smaller types to larger types, so information cannot be lost:
void func3(long l); func3(42);
A built-in type conversion is one that might lose information, such as converting a number to a smaller type, or a floating point to an integer. Certain conversions are better than others:
A conversion of a pointer to bool
is worse than other
conversions.
Converting a derived-class pointer to a base-class
pointer is better than converting the pointer to void*
.
Converting a derived-class pointer to void*
is better than converting
a base-class pointer to void*
.
When converting classes, class pointers, and
pointers to members, shorter distances in a class
hierarchy are better than longer distances; for example,
if A
inherits from
B
and B
inherits from C
, A*
to B*
is better than A*
to C*
.
The following are some examples of conversion transformations:
void func4(bool b); func4(3.14); void func5(void* ptr); func5(&x);
A user-defined conversion sequence has up to three parts: a standard conversion sequence followed by a single, user-defined conversion (constructor or type conversion operator) followed by another standard conversion sequence.
A standard conversion sequence is better than a user-defined conversion sequence. A user-defined conversion sequence is better than matching an ellipsis parameter.
If one sequence of transformations is a subsequence of another, the shorter sequence is better than the longer one.
Among sequences that differ only by qualification, the one with fewer qualification adjustments is better than one with more adjustments.
Example 5-23 shows
how overloaded functions are chosen. Notice that type promotions are
preferred to the conversion to Num
, even though Num
has an exact type conversion to
long
. Also note how an unsigned
long
cannot be promoted, so it must
undergo a built-in conversion. The compiler has no preference of
int
, long
or double
, so the conversion is ambiguous
and, therefore, results in an error. The same applies to long
double
; even though you might consider the
conversion to double
to be
"better" than conversion to int
,
the rules of overloading say otherwise. The final example results in
an error because there is no matching function. An array of wchar_t
cannot be converted to any of the
types used as func
parameters.
Example 5-23. Resolving overloaded functions
#include <string> void func(double); void func(long); void func(int); void func(const std::string&); class Num { public: Num(int i) : num_(i) {} operator long( ) const { return num_; } private: int num_; }; int main( ) { short n = 42; func(n); // func(int) func(Num(n)); // func(long) func(true); // func(int) func(3.1415f); // func(double) func("string"); // func(string); std::string s("string"); func(s); // func(string); func(3.14159L); // Error: ambiguous func(42UL); // Error: ambiguous func(L"widestr"); // Error: no match }