在此代码中:
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;
}
我收到一个错误:
_错误1错误C2446:':':没有从'RightSide *'转换为'LeftSide *'_
我认为(我看错了)我可以将指针从派生分配给基础而没有任何问题。那么问题出在哪里?
答案 0 :(得分:15)
问题不在于从LeftSide
或RightSide
到Side<T>
的转换。正如您原先认为的那样,这种转换会很好。
相反,问题在于这个表达式:
left < right ? new LeftSide<int> : new RightSide<int>
让我们稍微分解一下。三元运算符(在标准中称为“比较运算符”)如下所示:
bool_val ? lhs_expression : rhs_expression
请记住,整个构造本身就是一个表达。意味着它返回一个值,该值必须具有类型obv。 整个表达式的类型是从lhs_expression
和rhs_expression
的类型推导出来的。在这种情况下,您有LeftSide
和RightSide
。所以,这是你的问题。
LeftSide
和RightSide
除了拥有公共基类之外并不直接相关,并且它们之间没有可用的转换。 (你必须写一个。)所以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 :(得分:4)
FYI gcc失败了
error: conditional expression between distinct pointer types ‘LeftSide<int>*’ and ‘RightSide<int>*’ lacks a cast
将两者都转换为Side(int)*有效(但你可能已经知道了)
答案 2 :(得分: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>*
类型,左手可以转换为该类型,一切正常(并且编译器优化了额外的变量)。
答案 3 :(得分:0)
这两个应该是相同的类型,或者一个应该可以转换为另一个。
return left < right ? (Side<int>*)new LeftSide<int> : (Side<int>*)new RightSide<int>;