Effective C++ 第二十四條 Declare non-member functions when type conve
若所有參數(shù)皆需類型轉(zhuǎn)換,請(qǐng)為此采用 non-member 函數(shù)
考慮一個(gè)例子,有理數(shù)相乘是分子分母分別相乘,但是有理數(shù)也可以和整數(shù)相乘,整數(shù)轉(zhuǎn)換為有理數(shù)比 double 轉(zhuǎn)換為 int 要合理的多。
我們現(xiàn)在為 Rational 設(shè)置乘法運(yùn)算,有兩種考率:
設(shè)置 class 內(nèi)置 operator * 重載
設(shè)置 non-member 函數(shù)
下面先說第一種,重載運(yùn)算符
這類重載可以完美勝任乘法運(yùn)算,不會(huì)出錯(cuò)。
但是不能勝任混合運(yùn)算,不滿足與整數(shù)運(yùn)算的交換律
這很好理解,C * 2,C 在前,C 是 Rational ,內(nèi)置有 operator* 且參數(shù)為 Rational,此時(shí) 2 會(huì)被轉(zhuǎn)換為 Rational(2),也符合構(gòu)造函數(shù)構(gòu)造規(guī)則,構(gòu)造函數(shù)有缺省值,Rational(2)其實(shí)是 Rational(2,1);但是 2 * C 就無法運(yùn)算了,因?yàn)?2 是 int 型,不是 class ,沒有 operator* (Rational&)這樣的重載,也就是 int 不能和 Rational 做運(yùn)算。C * 2 嚴(yán)格來說不算 int 和 Rational 乘法,int 被轉(zhuǎn)換為了 Rational 才可以做運(yùn)算。也就是說重載運(yùn)算符不能滿足復(fù)雜運(yùn)算要求。而且一旦構(gòu)造函數(shù)是 explicit 修飾,無論是 C*2 還是 2*C 都無法通過編譯,都會(huì)出錯(cuò),因?yàn)?Rational 必須被顯式構(gòu)造,2 無法被隱式轉(zhuǎn)換為 Rational(2),也就無法進(jìn)行運(yùn)算了。
下面考慮第二種,non-member 函數(shù)
按照這種方法,無論是 Rational * int 還是 int * Rational 都可以完美通過。
可能有人問這里是否要聲明為 friend 函數(shù)呢?在這里其實(shí)不用,因?yàn)檫@里的實(shí)現(xiàn)不需要用到 Rational 的 private 成員變量,可以通過接口來實(shí)現(xiàn)。如果函數(shù)需要用到 private 成員變量,那么就可以聲明為 non-member friend 函數(shù)。第二種情況中這種 non-member 的 operator 重載非常值得注意,畢竟許多人的編程一定會(huì)加 friend ,其實(shí)并不需要。
總結(jié):
如果你需要為某個(gè)函數(shù)的所有參數(shù)(包括被 this 指針?biāo)赶虻哪莻€(gè)隱喻參數(shù))進(jìn)行類型轉(zhuǎn)換,那么這個(gè)函數(shù)必須是個(gè) non-member。