重载函数(overloaded function)

// const is irrelevent for nonreference parameters
Record lookup(Phone);
Record lookup(const Phone); // redeclaration

It is worth noting that the equivalence between a parameter and a const parameter applies only to nonreference parameters. A function that takes a const reference is different from on that takes a nonconst reference. Similarly, a function that takes a pointer to a const type differs from a function that takes a pointer to the nonconst object of the same type.

To explain how scope interacts with overloading we will violate this practice and use a local function declaration.

void print(const string &);
void print(double); // overloads the print function
void fooBar(int ival)
{
    void print(int); // new scope: hides previous instances of print, declaration is ok, but definition is not allowed.
    print("Value: "); // error: print(const string &) is hidden
    print(ival); // ok: print(int) is visible
    print(3.14); // ok: calls print(int); print(double) is hidden
}

The declaration of print(int) in the function fooBar hides the other declarations of print . It is as if there is only one print function available: the one that takes a single int parameter. Any use of the name print at this scope or a scope nested in this scopewill resolve to this instance.

When we call print , the compiler first looks for a declaration of that name. It finds the local declaration for print that takes an int . Once the name is found, the compiler does no further checks to see if the name exists in an outer scope. Instead, the compiler assumes that this declaration is the one for the name we are using. What remains is to see if the use of the name is valid. In C++ name lookup happens before type checking.

Overload Resolution with Multiple Parameters(含有多个形参的重载确定)

void f();
void f(int);
void f(int, int);
void f(double, double = 3.14);
f(42, 2.56);

The set of viable functions is selected in the same way. The compiler selects those functions that have the required number of parameters and for which the argument types match the parameter types. In this case, the set of viable functions are f(int, int) and f(double, double) . The compiler then determines argument by argument which function is (or functions are) the best match. There is a match if there is one and only one function for which

1、The match for each argument is no worse than the match required by any other viable function.(其每个实参的匹配都不劣于其他可行参数提供的匹配)
2、There is at least one argument for which the match is better than the match provided by any other viable function.(至少有一个实参的匹配要优于其他可行参数提供的匹配)

In this call, when we look only at the first argument, we find that the function f(int, int) is an exact match. To match the second function, the int argument 42 must be converted to a double. A match through a built-in conversion is "less good" than one that is exact. So, considering only this parameter, the function that takes two int s is a better match than the function that takes two double s.

However, when we look at the second argument, then the function that takes two double s is an exact match to the argument 2.56 . Calling the version of f that takes two int s would require that 2.56 be converted from double to int . When we consider only the second parameter, then the function f(double, double) is the better match.

This call is therefore ambiguous: Each viable function is a better match on one of the arguments to the call. The compiler will generate an error. We could force a match by explicitly casting one of our arguments:

f(static_cast<double>(42), 2.56); // calls f(double, double)
f(42, static_cast<int>(2.56)); // calls f(int, int)

 

The simplest kinds of conversion are integral promotions . Each of the integral types that are smaller than int(char, signed char, unsigned char, short , and unsigned short) is promoted to int if all possible values of that type fit in an int . Otherwise, the value is promoted to unsigned int . When bool values are promoted to int , a false value promotes to zero and true to one.

Conversions for expressions involving signed and unsigned int can be surprising. In these expressions the signed value is converted to unsigned . For example, if we compare a plain int and an unsigned int , the int is first converted to unsigned .

One important point to realize is that the small integral types promote to int . Given two functions, one of which takes an int and the other a short , the int version will be a better match for a value of any integral type other than short , even though short might appear on the surface to be a better match:

void ff(int);
void ff(short);
ff('a'); // char promotes to int, so matches f(int)

A conversion that is done through a promotion is preferred to another standard conversion. So, for example, a char is a better match for a function taking an int than it is for a function taking a double . All other standard conversions are treated as equivalent. The conversion from char to unsigned char , for example, does not take precedence over the conversion from char to double . As a concrete example, consider:

extern void manip(long);
extern void manip(float);
manip(3.14); // error: ambiguous call

The literal constant 3.14 is a double . That type could be converted to either long or float . Because there are two possible standard conversions, the call is ambiguous. No one standard conversion is given precedence over another.

Parameter Matching and Enumerations

Recall that an object of enum type may be initialized only by another object of that enum type or one of its enumerators. An integral object that happens to have the same value as an enumerator cannot be used to call a function expecting an enum argument:

enum Tokens {INLINE = 128, VIRTUAL = 129};
void ff(Tokens);
void ff(int);
int main() {
    Tokens curTok = INLINE;
    ff(128); // exactly matches ff(int)
    ff(INLINE); // exactly matches ff(Tokens)
    ff(curTok); // exactly matches ff(Tokens)
    return 0;
}

Although we cannot pass an integral value to a enum parameter, we can pass an enum to a parameter of integral type. When we do so, the enum value promotes to int or to a larger integral type. The actual promotion type depends on the values of the enumerators. If the function is overloaded, the type to which the enum promotes determines which function is called:

void newf(unsigned char);
void newf(int);
unsigned char uc = 129;
newf(VIRTUAL); // calls newf(int)
newf(uc); // calls newf(unsigned char)

The enum Tokens has only two enumerators, the largest of which has a value of 129. That value can be represented by the type unsigned char , and many compilers would store the enum as an unsigned char . However, the type of VIRTUAL is not unsigned char . Enumerators and values of an enum type, are not promoted to unsigned char , even if the values of the enumerators would fit.

posted on 2014-04-23 23:08  江在路上2  阅读(868)  评论(0)    收藏  举报