函数重载
基本用法
当一个函数需要根据不同的情况接收不同的参数时,以前的做法通常是为每一种可能的情况单独建立一个函数名,这样会造成代码非常臃肿。而有了函数重载之后,就可以用同一个函数名进行调用,虽然还是要根据不同的参数类型进行单独的实现,但是在调用的时候使用相同的函数名,并根据情况传入不同的参数即可,这样使得代码更加简洁。例如:
void print(const 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); //#1
print("Syrup"); //#5
print(1999.0, 10); //#2
print(1999, 12); //#4
print(1999L, 15); //#3
调用与原型不匹配
当调用与原型不匹配的时候,编译器会尝试将调用中的数据进行强制类型转换,以匹配可能的函数。例如:
print("Pancakes", 15.00); //#1,编译器将double强制转换成int
但是这种情况是原有函数签名中有唯一转换可能的情况,如果调用有多种转换的可能性,则编译器会报错,因为编译器不知道应该转换成哪一种函数签名。例如:
print(210u, 15);
该调用可以有三种转换的可能#2,#3,#4
,所以编译器会报错。
引用变量和普通变量不区分
对于下列函数:
double cube(double x);
double cube(double & x);
编译器在检查函数签名的时候不会将引用变量和普通变量加以区别
,所以这两个函数签名就是相同的。如果这样重载,编译器将会报错。
关于const变量与非const变量
如果一个函数为const变量
和非const变量
分别准备了不同的实现(声明了不同的函数签名),则编译器会根据调用参数是否为const变量而选择相应的函数实现。例如:
void dribble(char * bits); //#1
void dribble(const char * cbits); //#2
const char p1[20] = "How's the weather?";
char p2[20] = "How's the business?";
dribble(p1); //#1
dribble(p2); //#2
在调用函数时
,将一个const变量
赋值给一个非const变量
是非法的,因为赋值给一个非const变量
的时候编译器假设的是赋值完可以在函数内对该变量进行修改,而这与const变量
的属性相冲突。但是反过来将一个非const变量
赋值给一个const变量
是合法的。例如:
void constFun(const char * str);
void Fun(char * str);
const char p1[20] = "How's the weather?";
char p2[20] = "How's the business?";
constFun(p1); //合法
constFun(p2); //合法
Fun(p1); //非法
Fun(p2); //合法
函数类型不能作为区别
函数的返回类型不能作为函数签名中的一部分,这种说法很好理解,因为在调用函数的时候,都是函数名(参数列表)
的形式,这里不会注意到到函数的返回类型。所以以下两个函数其实是相同的函数签名:
long gronk(int n, float m);
double gronk(int n, float m);