Cpp Chapter 8: Adventures in Functions Part4

8.4 Function Overloading

) Function overloading, also called function polymorphism, lets you use multiple functions with the same name, but using different argument lists. The key to function overloading is a function's argument list, also called the function signature. The signature can differ in the number of arguments or in the type of arguments, or both.

) When there is one type mismatch between function calling and function prototype, C++ will accept this function call and conduct type conversion:

void process(double x, int y);
process(2,3); // acceptable, converting 2 to double(2.0)

But if the function call doen't match any of the prototypes while still could be converted to more than one prototype, C++ rejects this ambiguous function call:

void process(double x, int y);
void process(float x, int y);
process(2, 6); // invalid! 2 could be converted to both double and float

) This is not overloading:

void process(double x);
void process(double & x); // not overloading

due to the fact that the compiler considers a reference to a type and a type itself to be the same signature(to avoid ambiguous situations).

) The function-matching process also discriminates between const and non-const:

void process(double x);
void process(const double x); // overloaded

) Difference in the type of return value doesn't enable function overloading:

long process(double x);
double process(double x); // invalid!

Here's an example:

 1 // leftover.cpp -- overloading the left() function
 2 #include <iostream>
 3 unsigned long left(unsigned long num, unsigned ct);
 4 char * left(const char * str, int n = 1);
 5 
 6 int main()
 7 {
 8     using namespace std;
 9     char * trip = "Hawaii!!";
10     unsigned long n = 12345678;
11     int i;
12     char * temp;
13 
14     for (i = 1; i < 10; i++)
15     {
16         cout << left(n,i) << endl;
17         temp = left(trip,i);
18         cout << temp << endl;
19         delete [] temp;
20     }
21     return 0;
22 }
23 
24 // This function returns the first ct digits of the number num
25 unsigned long left(unsigned long num, unsigned ct)
26 {
27     unsigned digits = 1;
28     unsigned long n = num;
29 
30     if (ct == 0 || num == 0)
31         return 0;
32     while (n/=10)
33         digits++;
34     if (digits > ct)
35     {
36         ct = digits - ct;
37         while (ct--)
38             num /= 10;
39         return num;
40     }
41     else
42         return num;
43 }
44 
45 // This function returns a pointer to a new string consisting of the first n characters in the old string
46 char * left(const char * str, int n)
47 {
48     if (n < 0)
49         n = 0;
50     char * p = new char[n+1];
51     int i;
52     for (int i = 0; i < n && str[i]; i++)
53         p[i] = str[i];
54     while (i <= n)
55         p[i++] = '\0';
56     return p;
57 }

) Function overloading should be reserved for functions that perform the same task with different forms of data. Default arguments are someties useful replacement of function overloading when you require less arguments than a original function.

) Name decoration is the way that C++ handles overloaded functions. It assigns a secret identity, or code to each of the functions.

8.5 Function Templates

) A function template is a generic function description, it defines a function of a generic type which could be converted to specific types while passed corresponding parameter.This is also called generic programming:

template <typename T>
void Swap(T &a, T &b)
{
    T temp;
    temp = a;
    a = b;
    b = temp;
}

The keyword typename(could also be class) and template are obligatory. T is your choice of name representing a generic type. When you use a template function, The complier checks the argument types you use and then generates the corresponding function.

) Here is an example of function templates:

 1 // funtemp.cpp -- using a function template
 2 #include <iostream>
 3 
 4 template <typename T>
 5 void Swap(T &a, T &b);
 6 
 7 int main()
 8 {
 9     using namespace std;
10     int i = 10;
11     int j = 20;
12     cout << "i, j = " << i << ", " << j << ".\n";
13     cout << "Using complier-generated int swapper:\n";
14     Swap(i,j);
15     cout << "Now i, j = " << i << ", " << j << ".\n";
16     
17     double x = 24.5;
18     double y = 81.7;
19     cout << "x, y = " << x << ", " << y << ".\n";
20     cout << "Using complier-generated doulbe swapper:\n";
21     Swap(x,y);
22     cout << "Now x, y = " << x << ", " << y << ".\n";
23     return 0;
24 }
25 
26 template <typename T>
27 void Swap(T &a, T &b)
28 {
29     T temp;
30     temp = a;
31     a = b;
32     b = temp;
33 }

generally, the calling Swap(i,j) on line 14 will generate this function:

void Swap(int &a, int &j)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}

So using function templates doen't shorten code, it just provides extra reliability and save your precious time from making petty changes to functions.

posted @ 2018-09-27 10:39  Gabriel_Ham  阅读(169)  评论(0编辑  收藏  举报