2010-09-30 98 views
7

在此代碼:爲什麼我需要轉換?

template<class T> 
struct Side 
{ 
}; 

template<class T> 
struct LeftSide : public Side<T> 
{ 
}; 
template<class T> 
struct RightSide : public Side<T> 
{ 
}; 

Side<int>* f(int left, int right) 
{ 
    return left < right ? new LeftSide<int> : new RightSide<int>;//<---Here I'm returning either left or right side 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    return 0; 
} 

我得到一個錯誤:
_Error 1錯誤C2446: ':':沒有從轉換 'RightSide *' 到 '萊夫特賽德*' _

我我認爲(錯誤,因爲我看到),我可以分配指針從派生到基地沒有任何問題。那麼問題在哪裏?

回答

14

問題不是同來自LeftSideRightSideSide<T>轉換。正如你原先所想的那樣,這種轉換將會很好。

確切地說,問題是這樣表達:

left < right ? new LeftSide<int> : new RightSide<int> 

讓我們打破這一點。三元運算符(適當稱爲在標準作爲「比較操作符」)是這樣的:

bool_val ? lhs_expression : rhs_expression 

請注意,這整個構建體本身的表達式。這意味着它返回一個值,它必須有一個類型obv。從lhs_expressionrhs_expression的類型推導出整體表達式的類型。在這種情況下,您有一個LeftSide和一個RightSide。所以,這是你的問題。

LeftSideRightSide彼此沒有直接關係,除了有一個共同的基類,並且它們之間沒有可用的轉換。 (你必須寫一個)。因此沒有bool_val ? lhs_expression : rhs_expression可以擁有的單一數據類型。你可能會認爲,「嗯,愚蠢的編譯器,爲什麼不只是找出共同的基類並使用它?」這確實有點痛苦。拋開它的正確或錯誤的論點,它不會那樣工作。

您有兩種選擇。

一,使用更簡單的結構:

if(left < right) 
    return new LeftSide<int>; 
else 
    return new RightSide<int>; 

兩個,如果你真的真的想用三元運算符(是哪種情況有時),你需要填鴨式它的數據類型,編譯器:

Side<int>* f(int left, int right) 
{ 
    return left < right ? static_cast<Side<int>*>(new LeftSide<int>) : static_cast<Side<int>*>(new RightSide<int>);// now you're good 
} 
+1

(1)你可以不寫用戶自定義轉換betweem指針類型。 (2)您只需修改一個操作數的類型即可使其工作。 (3)由於存在隱式轉換,所以即使'static_cast'也是過量的,static_cast'可以防止編譯器警告合法的類型安全問題。 – 2010-09-30 21:56:32

4

我覺得呢? :運營商要求2種選擇是相同的類型;不是他們可以轉換爲同一類型

僅供參考gcc的失敗一樣

error: conditional expression between distinct pointer types ‘LeftSide<int>*’ and ‘RightSide<int>*’ lacks a cast 

鑄造既側(INT)*作品(但你可能已經知道了)

+2

轉換是好的,但一個操作數必須是可轉換到其它的類型。如果允許任何類型,則在一般情況下問題變得棘手。 – 2010-09-30 18:44:59

+1

我認爲你是對的,但它太soaoo dissapointing! – 2010-09-30 18:47:36

2

你想同時分支返回Side<int>*,但編譯器不知道,Side<int>類型不會出現在該表達式的任何位置。

因爲我不喜歡當一個隱式轉換存在使用一個演員,我會寫爲:

if (left < right) return new LeftSide<int>; 
return new RightSide<int>; 

但是,如果你想使用一個三元運算符,

Side<int>* i_want_this_type; 
return (left < right) ? new LeftSide<int> : (i_want_this_type = new RightSide<int>); 

現在右手分支是Side<int>*,左手可轉換爲該類型,一切正常(並且編譯器優化了額外的變量)。

+0

downvote的原因? – 2010-09-30 18:48:34

+0

我不會有d/v'ed,但我猜測這是因爲你引入了一個臨時 - 即使是編譯器可能優化的臨時編譯器。 – 2010-09-30 19:15:26

0

這兩個應該是相同的類型,或者一個應該可以轉換到另一個。

return left < right ? (Side<int>*)new LeftSide<int> : (Side<int>*)new RightSide<int>; 
+0

C風格演員在這裏完全是過度殺傷力。 – 2010-09-30 18:49:15

+0

並殘忍醜陋和老外的日期程序員hasbeen亂砍上下的 – 2010-09-30 19:24:27

相關問題