C++ 函數重載解析策略

參考《C++ Primer Plus》(第6版)中文版 , Stephen Prata 著,張海龍 袁國忠譯,人民郵電出版社 。C++ 使用重載解析策略來決定為函數調用使用哪一個函數定義 。重載解析過程大致分為如下三步:

  • 第 1 步:創建候選函數列表 , 只要求函數名一樣即可,對函數特征標以及是否為模板函數無要求;
  • 第 2 步:在上一步的基礎上創建可行函數列表,包含特征標完全匹配的常規函數或模板函數、以及實參隱式轉換后完全匹配的常規函數或模板函數,這些都是參數數目正確的函數;
  • 第 3 步:在上一步的基礎上確定最佳匹配函數,若有則使用它,若沒有則該函數調用失敗 。
下面以一個例子來說明這個重載過程:
//全部函數原型void may(int);//原型#1float may(float, float = 3);//原型#2void may(char);//原型#3char * may(const char *);//原型#4char may(const char &);//原型#5template<class T> void may(const T &);//原型#6template<class T> void may(T *);//原型#7void may(char, double);//原型#8void mbk(float);//原型#9char mkk(int, char);//原型#10int mck(char);//原型#11double myk(float);//原型#12void mpk(char);//原型#13//函數調用may('B');//函數定義...重載第 1 步:創建候選函數列表 。即函數名稱為 may 的常規函數和模板函數,候選函數列表如下:
//重載第1步:創建候選函數列表void may(int);//原型#1float may(float, float = 3);//原型#2void may(char);//原型#3char * may(const char *);//原型#4char may(const char &);//原型#5template<class T> void may(const T &);//原型#6template<class T> void may(T *);//原型#7void may(char, double);//原型#8重載第 2 步:創建可行函數列表 。由于整數類型 char 不能被隱式地轉換為指針類型 char * , 因此函數 #4 和函數 #7 都被排除,而函數 #8 因為參數數目不匹配也會被排除 。進行完全匹配時,C++ 允許下表這些無關緊要的轉換 , 表中 Type 表示任意類型,例如 char &const char & 的轉換也包含在內,表中 Type (argument-list) 意味著用作實參的函數名和用作形參的函數指針只要返回類型和參數列表相同,就是匹配的 。
實參類型形參類型TypeType &Type &TypeType []Type *Type (argument-list)Type (*) (argument-list)Typeconst TypeTypevolatile TypeType *const Type *Type *volatile Type *根據此表可知,剩下的函數中包含特征標完全匹配的常規函數 #3#5、特征標完全匹配的模板函數 #6(此時 T 可以被實例化為 char)、實參隱式轉換后完全匹配的常規函數 #1#2 ??尚泻瘮盗斜砣缦拢?br /> //重載第2步:創建可行函數列表void may(int);//原型#1float may(float, float = 3);//原型#2void may(char);//原型#3char may(const char &);//原型#5template<class T> void may(const T &);//原型#6重載第 3 步:確定最佳匹配函數 。通常,從最佳到最差的順序如下所述:
  1. 特征標完全匹配;
  2. 類型需經隱式提升轉換,例如 charshort 自動轉換為 intfloat 自動轉換為 double;
  3. 類型需經隱式標準轉換,例如 int 轉換為 char,long 轉換為 double;
  4. 類型需經隱式自定義轉換,例如類中用戶定義的類型轉換 。
依此規則 , 函數 #3 和函數 #5、函數 #6 都是特征標完全匹配的最佳匹配函數,函數 #1 需經隱式提升轉換,函數 #2 需經隱式標準轉換 , 由此各函數最佳匹配程度為:(#3, #5, #6) > #1 > #2 。當特征標完全匹配時,又有如下規則:
  • 指向非 const 數據的指針和引用優先與形參為非 const 指針和引用的函數匹配;
  • 優先與非模板函數匹配;
  • 同為模板函數時,優先與較具體的模板函數匹配 。
依此規則,非模板函數 #3#5 最佳匹配程度要高于模板函數 #6,即各函數最佳匹配程度為:(#3, #5) > #6 > #1 > #2 。最終出現了兩個最佳匹配函數 #3#5,因此該函數調用失敗 , 編譯器將報錯 。

推薦閱讀