编译器选择哪个函数版本
对于函数重载,函数模板和函数模板重载,C++需要一个定义良好的策略,主要以以下步骤运行
第一步:创建候选函数列表。其中包含与被调用函数的名称相同的函数和模板函数。
第二步:使用候选函数列表创建可行函数列表。这些都是参数数目正确的函数,为此有一个临时转换序列,其中包括实参类型和相应的形参类型完全匹配的情况。
第三步:确定是否有最佳的可行函数,如果有则使用它,否则该函数调用出错。
如下面调用:
void may(int); //#1 float may(float,float=3); //#2 void may(char); //#3 char* may(char *); //#4 char may(const char &); //#5 template<class T>void may(const T&); //#6 template<class T>void may(T*); //#7
may('B');
只考虑特征标,不考虑返回类型,则#4和#7不可行。剩下5个可行的函数,从最佳到最差的顺序如下所述。
1 完全匹配,但常规由于模板。
2 提升转换,(例如,int和shorts自动转换为int,float自动转换为double)。
3 标准转换 (例如,int 转换为char,long自动转换为double)。
4.用户自定义的转换,如类声明中定义的转换。
其中#3,#5,#6都是完全匹配,但是#6为模板,故剩余#3,#5进行选择,这需要更深入的探讨。
完全匹配和最佳匹配
struct blot {int a;char b[10];}; blot int = {25,"spots"}; /* `````` */ recycle(ink); void recycle(blot); void recycle(const blot); void recycle(blot&); void recycle(const blot&);
上面原型都是完全匹配的,如果有多个匹配原型,则会生错误消息,可能是二义性这样的报错。
然而,有的时候,即使两个函数都是完全匹配,仍可完成重载解析。
指向非const的指针和引用优先于非const的指针和引用。
如果完全匹配的两个函数都是模板函数,则较具具体的模板函数优先,即编译器执行的转换最少。
template <class Type> void recycle (Type t); //#1 template <class Type> void recycle (Type *t); //#2 blot ink={25,"spots"}; recycle(&ink);
recycle(&ink)与#1模板匹配,Type被解释为blot*,与#2匹配被解释为blot。
recycle<blot*>(blot*)被认为是更具体的。因为在#2中,Type已经被具体化为指针。
struct debts { char name[50]; double amount; }; template<typename T> void showarray(T arr[], int n) { cout << "template a:"<<endl; for (int i = 0; i < n; i++) { cout << arr[i] << ' '; } cout << endl; } template<typename T> void showarray(T *arr[], int n) { cout << "template b:" << endl; for (int i = 0; i < n; i++) { cout << *arr[i] << ' '; } cout << endl; } int main() { int things[6] = { 13,31,103,301,310,130 }; struct debts mr_E[3] = { {"Ima Wolfe",2400.0}, {"Ura Foxe",3889.2}, {"Iby stout",231.3} }; double* pd[3]; for (int i = 0; i < 3; i++) { pd[i] = &mr_E[i].amount; } showarray(things, 6); cout << "mr_E's debts:" << endl; showarray(pd, 3); }
结果:
template a: 13 31 103 301 310 130 mr_E's debts: template b: 2400 3889.2 231.3

浙公网安备 33010602011771号