最近在工作中遇到乙個問題——編寫乙個c++類,擁有多個類,其中有乙個類可以轉換到其它所有的類,比如:
class a {};
class b {};
class c
operator b() const
};
另外,在全域性還定義(過載)了幾個函式:
void func(const a &a, const a &b);
void func(const b &a, const b &b);
這時候,當使用者呼叫func函式,並傳入c的物件的時候,例如:
c a, b;
func(a, b);
編譯器會報出錯:
test.cpp: in function 『int main()』:
test.cpp:23: error: call of overloaded 『func(c&, c&)』 is ambiguous
test.cpp:14: note: candidates are: void func(const a&, const a&)
test.cpp:17: note: void func(const b&, const b&)
問題的根源在於,由於c定義了兩個自定義型別轉換函式,分別轉換到a和b,在呼叫func函式的時候,編譯器也無法知道該呼叫哪個版本的func函式,從而只能報錯。
我們希望c的物件在呼叫其它函式的時候能夠轉換成a或者b的物件,但是在呼叫func函式的時候,我們只希望它預設轉換成a。剛開始我認為這個問題很好解決,只需要對**略做調整,乙個小時就能搞定。但是深入做起來以後,發現裡面包含了很多c++的知識,而我平時都沒有引起重視。通過解決這個問題也讓我學到不少東西,讓我對c++的型別轉換和函式、運算子過載有了全新的認識。
我打算分上中下三篇文章分別介紹我想到的和學習到的一些解決方法。上篇主要介紹一些及其簡單的方法。在某些情形下也許能夠很簡單的解決問題,但在我的實際工作中,由於各種各樣的原因,無法使用。中篇將介紹乙個比較複雜但基本可行的辦法,雖然在某些情況下仍然存在一些問題。下篇我將給出我最後想到的一種解法,能夠完整地解決這個問題。
解法一:明確型別轉換
最簡單和直接的解決辦法是要求使用這個庫的使用者在呼叫這個函式地時候,明確地指明需要將class c轉換成哪乙個類:
func((a)a, (a)b);
這種解法雖然簡單而且直接,最重要的是它體現了一種良好的程式設計習慣,但是為了保證向上相容性,我們不得不捨棄這種做法。因為我們無法要求使用者因為這個改變,改掉所有現有的**。
解法二:暴力新增新的過載函式
第二種方法也很直接——既然不能要求使用者新增強制型別轉換,我們就為c過載func函式,然後再呼叫正確的版本:
void func(const c &a, const c &b)
同樣地,這種解法也能解決問題。但是,這種解法也有其侷限性。在我們的具體問題中,我們不光擁有c類,我們還擁有很多類似c這樣的類,都能同時轉換成a和b,例如:
class d
operator b() const
};
那麼我們就需要為每個類過載乙個這樣的函式。而且我們希望支援這樣的呼叫:
c cc;
d dd;
func(cc, dd);
這樣一來,我們就需要也過載:
void func(const c &a, const d &b);
void func(const d &a, const c &b);
如果還有類似的很多類,例如e-z,如果以後需要支援乙個函式擁有三個或者跟多的引數,那麼這樣的排列組合就是天文數字。 C 運算子過載與型別轉換
當乙個過載的運算子是成員函式時,this繫結到左側運算物件。成員運算子函式的 顯式 引數數量比運算物件的數量少乙個。通常情況下,不應該過載逗號 取位址 邏輯與和邏輯或運算子。關於過載運算子的返回型別 應與其內建版本的返回型別相容 邏輯和關係運算子應該返回bool,算術運算子應該返回乙個類型別,賦值運...
過載 型別轉換與運算子
轉換建構函式和型別轉換運算子共同定義了類型別轉換 class type conversions 型別轉換運算子 型別轉換運算子是類的一種特殊成員函式,它負責將乙個類型別的值轉換成其他型別。型別轉換函式的一般形式如下所示 operator type const 其中type表示某種型別。型別轉換運算子...
過載 型別轉換與運算子
前面我們看到由乙個實參呼叫的非顯式建構函式定義了一種隱式的型別轉換,這種建構函式將實參型別的物件轉換成類型別。我們同樣能定義對於類型別的型別轉換,通常定義型別轉換運算子可以做到這一點。轉換建構函式和型別轉換運算子共同定義了類型別轉換,這樣的轉換有時也被稱作使用者定義的型別轉換。型別轉換運算子 型別轉...