天天看點

【轉】函數重載解析

<<C++ Primer>>學習筆記---函數重載解析

一、普通重載函數的解析

    重載函數的解析可以分為三個步驟來執行:1.查找候選函數,并檢查函數調用實參表的屬性;2.選擇可行函數;3.對函數實參到形參的轉換進行分級,并選出最佳可行函數。下面對各個步驟進行詳細的叙述。

1.查找候選函數,并檢查函數調用實參表的屬性

    所有在調用點可見的同名函數聲明,及當調用函數的實參中有名字空間成員時該名字空間中所有同名函數都将被添加到候選函數集合中,另外當函數實參是類類型時還将把這個類聲明中與調用函數同名的友元函數加入到候選函數集合中。值得注意的是當調用點處在某個局部域中而且在全局域和這個局部域中都有同名的函數聲明時,全局域的函數聲明被局部域覆寫而不被加入到候選函數集合中。這之後編譯器還将對函數調用的實參表根據實參的數量和類型進行分析。

2.選擇可行函數

    可行函數集是候選函數集的一個子集,所有能夠用函數實參進行相關類型轉換調用的函數都将被加入到這個集合中。

3.對函數實參到形參的轉換進行分級,并選出最佳可行函數

    考慮可行函數集中每個函數調用時實參需要進行的類型轉換級别,每個實參的一系列類型轉換可以描述為一個轉換序列。一般的标準轉換序列是這樣一個序列:左值轉換->提升、标準轉換->限定修飾符轉換;另外使用者定義的轉換序列是這樣一個序列:标準轉換用->戶定義的轉換->标準轉換,也就是說使用者定義轉換序列中是不允許兩個或多個使用者定義的轉換在同一個轉換序列中出現。評判一個轉換序列的好壞的标準是考察這個轉換序列中最低級别的一個轉換。當兩個轉換序列中最低級别的轉換相同時則需要限定修飾符轉換的序列比不需要限定修飾符轉換的序列差。當兩個重載函數中形參到實參的轉換序列中包含相同的使用者定義轉換,那麼判斷這個轉換序列的好壞标準是之前(或之後)的一個标準轉換。當這兩個序列中的使用者定義轉換不同時,那麼将不作比較直接出現二義性錯誤。

    所有的轉換被分為精确比對、提升、标準轉換、使用者定義的轉換。這些轉換被分級,其中精确比對好于提升,提升好于标準轉換,标準轉換好于使用者定義的轉換。

    所謂限定修飾符轉換指的是從非指向常量的指針實參到指向常量的指針形參之間的轉換。而按值傳遞中形參與實參的常量于非常量之間并不存在任何轉換。

二、類成員函數的重載解析

    對于類中的成員函數也能重載,當解析這些類的成員函數重載時,隻考慮::,.,->的左操作數所代表類域中相關函數的名字。當然解析過程首先進行,并遵循在(一)中描述的細節,此時并不考慮通路權限。當解析結束後編譯器将檢查最佳可行函數的通路權限,如果不可方位則出現編譯錯誤。

三、操作符重載的解析

    操作符解析的過程也遵循(一)中描述的步驟和細節,其唯一的不同之處在于候選函數的集合,操作符重載的解析過程中候選函數集合是以下幾個集合的并集:1.調用點可見的同名函數;2.對于有實參在名字空間中定義,則名字空間中定義的同名函數;3.如果實參是類類型,則類中同名的友元函數;4.如果操作符的左操作符是類類型,則類中同名的操作符重載成員函數;5.内置類型的操作符重載成員函數。

四、模闆函數的重載解析

    普通函數和模闆函數可以構成一個重載集合。對于這種重載集合,首先将在調用點根據函數實參對模闆參數進行推演,當模闆參數推演成功,如果此時不存在相應參數的模闆特化那麼通用模闆的相應執行個體化将被放入候選函數集合否則模闆特化将被放入候選函數集合。值得注意的是當模闆參數推演失敗時并不會有任何模闆函數的執行個體化或者特化被放入候選函數集中。當模闆解析過程中出現模闆執行個體化和普通函數産生二義性時模闆函數将被删除,普通函數由于擁有較高的優先性而被選擇。

五、繼承對于重載解析的影響

    繼承對于重載解析的影響展現在兩個方面:

1.對于候選函數和可行函數的影響:由于派生類的函數會覆寫掉基類的同名函數而不是形成一個重載函數集,是以會對候選函數和可行函數的集合中函數的數量産生影響。

2.對于轉換的影響:派生類對象、指針、引用到基類對象、指針、引用的轉換都被視作标準轉換,而基類對象、指針、引用到派生類的對象、指針、引用并不存在隐式轉換。

繼續閱讀