函数重载的关键是函数的参数列表——也称为函数特征标(function signature).
如果两个函数的参数数目和类型相同,同时参数的排列顺序也相同,那么它们的特征标相同,而变量名是无关紧要的。
以下是正确的函数重载实例:
viod print(const char * str,int width);
viod print(double d, int width);
viod print(long l,int width);
viod print(int i,int width);
viod print(const char * str);
使用被重载的函数时,需要在函数调用中使用正确的参数类型。否则编译器将尝试使用标准类型转换强制进行匹配。如果发现可与多个函数特征标进行类型转换匹配,将被视为错误。
错误实例:
double cube(double x);
double cube(double & x);
这里它们的特征标看起来不同。
假设cube(x)这样调用,参数x 与double x 原型和double &x 原型都匹配,编译器无法确定使用哪个原型。
因此编译器在检查函数特征标时,把类型引用和类型本身视为同一特征标。
同时,匹配函数时,并不区分const和非const变量。
但在类中,可以实现普通成员函数和常量成员函数的重定义:
class Ex
{
public:
void f(int i){ int j=i;} //#1
void f(int i)const (int j=i;) //#2
};
函数返回类型并不能作为特征标来区分。因此要重载不同的返回类型,那么参数也必须不同。
编译器如何实现函数重载。
编译器根据函数原型中指定的形参类型对每个函数名进行加密处理,称之为(名称修饰 或 名称矫正)。
这是一个未加密的函数原型:
long MyFunctionFoo (int, float);
加密后显示为:
?MyFunctionFoo@@YAXH@Z
对原始名称进行的表面看来无意义的加密将对参数数目和类型进行编码。添加的一组符号随函数特征标而异,而加密使用的约定随编译器而异。