2010/11/10
关键字:函数重载、函数指针
函数重载
出现在相同作用域中的两个函数,如果具有相同的名字而形参表不同,则称为重载函数(overloaded function)。
main函数不能重载。
如果两个函数声明的返回类型和形参完全相同,则将第二个函数声明为第一个的重复声明。如果形参表完全相同,但是返回类型不同,则第二个声明是错误的。
编译器会忽略函数的形参名字,下面的声明是等价的:
void func(int i);
void func(int );
重载函数查找的顺序是先名字后参数类型。
函数匹配
函数重载确定即函数匹配是将函数调用与重载函数集合中的一个函数相关联的过程。通过自动提取函数调用中实际使用的实参与重载集合中各个函数提供的形参做比较,编译器实现该调用与函数的匹配。匹配的结果有三种:
1. 编译器找到与实参最佳匹配(best match)的函数,并生成调用该函数的代码。
2. 找不到形参与函数调用实参匹配的函数,编译器会给出编译错误。
3. 存在多个与实参匹配的函数,但没有一个是明显的最佳选择。这种情况也是错误的,编译器会给出二义性(ambiguous)编译错误。
重载确定有三个步骤:
1. 候选函数
找出名字相同的函数形成重载集合
2. 选择可行函数
首先检查形参个数是否匹配,然后检查类型是否匹配(或者实参可被隐式转换成形参类型)
3. 选择最佳匹配
考虑每个实参,选择对应形参与之最匹配的一个或多个可行函数。精确匹配优于类型转换。
转换等级降序排列:
a. 精确匹配
b. 通过类型提升实现的匹配
c. 通过标准转换实现的匹配
d. 通过类类型转换实现的匹配
含有多个形参的重载确定
编译器依次检查每一个实参来决定哪个或哪些函数匹配最佳。如果有且仅有一个函数满足下列条件,则匹配成功:
a. 其每个实参的匹配都不劣于其他函数
b. 至少有一个实参的匹配优于其他可行函数。
void f(int);
void f(short);
void f1(long);
void f1(float);
int _tmain(int argc, _TCHAR* argv[])
{
f('a'); //匹配到void f(int),因为char类型转换成int是类型提升,而转换成short是标准转换
f1(2.12); //没有匹配到函数,因为2.12是double类型,转换成float和long都是标准转换,具有二义性
return 0;
}
枚举类型和参数匹配
无法将整型值传递给枚举类型的形参,但可以将枚举值传递给整型形参。此时枚举值会被提升到int或更大的整型。具体的提升类型取决于枚举成员的值和具体的机器。
void f2(unsigned char){};
void f2(int){};
enum CODE {OK = 128, ERROR = 129};
int _tmain(int argc, _TCHAR* argv[])
{
f2(OK); //枚举成员被提升为int,虽然unsigned char可以保存的下128
重载和const形参
仅当形参为引用或指针时,形参是否为const才有影响。形参是实参的副本时,形参是否为const和非const没有区别。
不能基于指针本身是否为const实现函数重载,f(int *)和f(int *const)重复定义。
f(int *)和f(const int *)不同。
指向函数的指针
函数指针的类型由函数返回值类型和形参表确定,与函数名无关。
typedef bool(*cmpFcn)(const string &, const string &);
可以声明cmpFcn为函数指针类型。
假设bool SomeFunc((const string &, const string &);
cmpFcn fuc1 = SomeFunc;
cmpFcn fuc1 = &SomeFunc;
两者等效。
函数指针只能通过同类型的函数或函数指针或0值常量表达式初始化和赋值。
指向不同函数类型的指针不存在转换。
函数指针做形参有两种写法:
void f(bool(const string &, const string &));
void f(bool (*)(const string &, const string &));
函数返回指向函数的指针
int (*f(int)) (int *);
看这类声明语句需要从内向外看。
内层是f(int)是一个函数,外层int (*) (int *)函数指针。表示的是返回函数指针的函数。
用typedef更容易理解,
typedef int (*F) (int *);
F f(int);
允许将形参定义为函数类型,实际调用时实参是对应的函数指针。但不允许将函数返回值定义为函数类型,只能是函数指针类型。
typedef int F(int); //F为函数类型
void f1(F); //ok
void f1(F*) //ok
F f2(); //error
F* f2(); //ok
指向重载函数的指针
C++允许使用指针指向重载函数:
void f(double);
void f(short);
typedef void (*F)(int);
F = f; //error,必须和所指向的函数类型完全匹配