Problemem jest z konwersją z obu LeftSide
lub RightSide
do Side<T>
. Jak pierwotnie sądziliście, ta konwersja byłaby w porządku.
raczej problem jest z tym wyrażeniem:
left < right ? new LeftSide<int> : new RightSide<int>
Złammy to trochę w dół. Operator trójskładnikowych (właściwie określone w normie jako „operatora porównania”) wygląda następująco:
bool_val ? lhs_expression : rhs_expression
Należy pamiętać, że cała ta konstrukcja jest sama w sobie wyrazem. Oznacza to, że zwraca wartość, która musi mieć typ, obv. Typ całego wyrażenia wywodzi się z typów lhs_expression
i rhs_expression
. W takim przypadku masz numer LeftSide
i RightSide
. Oto twój problem.
LeftSide
i RightSide
nie są bezpośrednio ze sobą powiązane, oprócz wspólnej klasy bazowej i nie ma między nimi żadnej konwersji. (Musiałbyś napisać jeden.) Więc nie ma jednego typu danych, który może mieć bool_val ? lhs_expression : rhs_expression
. Możesz pomyśleć: "no, głupi kompilator, dlaczego nie po prostu wymyślić wspólną klasę bazową i użyć tego?" To jest rzeczywiście trochę uciążliwe. Pozostawiając na boku argument, że jest dobry lub zły, to po prostu nie działa w ten sposób.
Masz dwie opcje.
Jeden użyć prostszą konstrukcję:
if(left < right)
return new LeftSide<int>;
else
return new RightSide<int>;
dwa, jeśli naprawdę naprawdę chcesz użyć operatora potrójny (który jest przypadek czasami), trzeba łyżka karmić kompilator To datatypes:
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) Nie można pisać konwersji definiowanych przez użytkownika pomiędzy typami wskaźników. (2) Trzeba tylko ustalić typ jednego operandu, aby działał. (3) Nawet 'static_cast' jest przesadą, ponieważ istnieje niejawna konwersja, a' static_cast' może uniemożliwić kompilatorowi ostrzeganie o uzasadnionych problemach z bezpieczeństwem typu. –