3.20 函数重载
C++ 允许定义多个同名函数,只要这些函数有不同参数集(至少有不同类型的参数)。这个功 能称为函数重载(function overloading)。调用重载函数时,C++编译器通过检查调用中的参数个数、 类型和顺序来选择相应的函数。函数重载常用于生成几个进行类似任务而处理不同数据类型的同名 函数。
编程技巧3.15
用函数重载完成类似的任务可以使程序易于阅读和理解。
图3.25用重载函数square计算int类型值的平方以及double类型值的平方。第8章将介绍如何 重载运算符,定义其如何对用户自定义数据类型的对象进行操作(事实上,我们已经使用了许多已重载的运算符,包括流插入运算符 << 和流读取运算符 >>。第8章将详细介绍重载 >> 和 <<)。3.21节介绍的函数模板自动产生重载函数,对不同数据类型完成相同的任务。第12章将详细介绍函数模板和类模板。
// Fig. 3.25: fig03_25.cpp // Using overloaded functions #include <iostream.h> iht square( iht x ) { return x * x; } double square( double y ) { return y * y; } int main(){ cout << "The square of integer 7 is" << square( 7 ) << "\nThe square of double 7.5 is" << square( 7.5 ) << endl; return 0; }
输出结果:
The square of integer 7 is 49 The square of double 7.5 is 56.25
图 3.25 使用重载函数
重载函数通过签名(signature)进行区别,签名是函数名和参数类型的组合。编译器用参数个数和类型编码每个函数标识符(有时称为名字改编或名字修饰),以保证类型安全连接(type-safelinkage)。类型安全连接保证调用合适的重载函数井保证形参与实参相符。编译器能探测和报告连接错误。图3.26的程序在Borland C++编译器上编译,我们不显示程序执行的输出,图中用汇编语言输出了由Borland C++编译器产生的改编函数名。每个改编名用@加上函数名,改编参数表以$q开头。在函数nothing2的参数表中,zc表示char、i表示int、pf表示float*、pd表示double*。在函数nothing1的参数表中,i表示int、f表示float、zc表示char、pi表示int*。两个square函数用参数表区分,一个指定d表示double,一个指定i表示沁。函数的返回类型不在改编名称中指定。函数名改编是编译器特定的。重载函数可以有不同返回类型.但必须有不同参数表。
常见编程错误3.33
用不同返回类型和相同参数表生成重载函数是个语法错误。
// Name mangling lnt square( int x ) ( return x * x; } double square( double y ) ( return y * y; } void nothing1( int a, float b, char c, int *d ){} // empty function body char *nothing2( char a, int b, float *c, double *d ){ return 0; } int main(){ return 0; }
输出结果:
public _main public @nothing2$qzcipfpd public @nothing1$qifzcpi public @square$qd public @square$qi
图3.26 名字改编以保证类型安全连接
编译器只用参数表区别同名函数。重载函数不一定要有相同个数的参数。程序员使用带默认参数的重载函数时要小心,以免出现歧义。
常见编程错误3.34
调用省略默认参数的函数时可能与调用另一重载函数相同,这是个语法错误。例如,如果程序中的函数不带参数,有一个同名函数包含全部默认参数,则不带参数调用这个函数时就会造成语法措误。