函数重载(function overloading)
函数重载是编辑器干的活,把本来需要程序员做的任务让编译器做了。
用法就是:定义两个名字一样的函数,但是调用的参数值类型不一样,这样在编译的时候,编译器会根据调用情况选择使用特定的函数。每个函数的功能不一定相同。
好处是编写程序的时候不用考虑那么多类型相符情况,一个函数可以对应多种类型的参数,可以对每种类型分别进行处理。
比如:
void print(cost char * str, int width); // #1
void print(double d, int width); // #2
void print(long l, int width); // #3
void print(int i, int width); // #4
void print(const char *str); // #5
函数调用:
print(“Pancakes”, 15); // use #1
print(“Syrup”); // use #5
print(1999.0, 10); // use #2
print(1999, 12); // use #4
print(1999L, 15); // use #3
函数名字只有一个print,函数调用的时候,编译器会根据不同的参照值选择不同的函数原型。函数原型的定义可以随便编写,跟普通函数一样。
函数继承(Function Templates)
函数继承类似于重载,也是根据调用的参数类型选用函数。不过这里编译器做的工作更多,是根据定义的模板函数和调用的参数类型,按照调用类型的种类,重新定义很多个函数。每个函数的功能都一样,但是参数类型和返回值类型都不同。
template<typename AnyType>
void swap(AnyType &a, AnyType &b)
{
AnyType temp;
temp = a;
a = b;
b = temp;
}
这里,AnyType可以是任意类型。比如定义int a,b; 调用swap(a,b)的时候,编译器就定义一个int类型的函数void swap(int &a, int &b)。如果定义char a,b; 调用swap(a, b)的时候,编译器就定义一个char类型的函数 void swap(char &a, char &b).就是调用的时候,编译器会把AnyType换成响应的数据类型,然后定义函数。
重载加继承
重载和继承可以放在一起使用:
template <typename T> // or class T
void Swap(T & a, T & b);
template<typename T>
void Swap(T * a, T * b, int n);
编译器根据调用情况编译出各种函数原型。比如 int i, j; 调用Swap(i, j)就编译出void Swap(int & a, int & b); int d1[5], d2[5];调用Swap(d1, d2, 5)就编译出 void Swap(int * a, int * b, int n).
指定继承函数
可以针对特定类型指定继承函数。
template<typename T> void Swap(T &, T &); // #1
template <> void Swap<job>(job &, job &); // #2
如果对于job类型有两个定义:job a,b; 调用Swap(a, b)时两个继承都符合条件,但是由于#2有<job>指定符号,所以调用的时候编译器会按#2来编译函数原型。
#2可以简写为 template <> void Swap(job &, job &);
重载流程
1,查找名称相同的函数;
2,查找主函数中调用过的参数类型,根据这些类型确定需要重载的函数;
3,根据调用情况编译函数原型,如果没有这种类型就返回错误,如果有两个都符号要求同样返回错误。
重载优先级
1,严格符合类型,常规函数优先于模板函数;
2,向上兼容(比如char和short型可以用于int定义的函数,float可以用于doule定义的函数);
3,标准转换(比如int转换为char,long转换为double);
4,用于定义的转换,如类声明中定义的转换。
当重载和继承一起出现的时候,重载选用符号最少原则。
比如
template <typename T > void f(T x); // #1
void f(int x); // #2
如何对 int a; 调用f(a), 就使用#2,此时T没有表示.
又比如
template<typename T> void f(T x); // #1
template<typename T> void f(T * x); //
如果定义 int *b; 调用f(b) 的时候,重载可以#1使T为int *,#2可以使T为int,根据符号最少,编译器选择#2.