我为什么需要转换?

时间:2010-09-30 18:39:05

标签: c++

在此代码中:

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 *'_

我认为(我看错了)我可以将指针从派生分配给基础而没有任何问题。那么问题出在哪里?

4 个答案:

答案 0 :(得分:15)

问题不在于从LeftSideRightSideSide<T>的转换。正如您原先认为的那样,这种转换会很好。

相反,问题在于这个表达式:

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

让我们稍微分解一下。三元运算符(在标准中称为“比较运算符”)如下所示:

bool_val ? lhs_expression : rhs_expression

请记住,整个构造本身就是一个表达。意味着它返回一个值,该值必须具有类型obv。 整个表达式的类型是从lhs_expressionrhs_expression的类型推导出来的。在这种情况下,您有LeftSideRightSide。所以,这是你的问题。

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 :(得分:4)

我认为那个? :运算符要求2个选项属于同一类型;并不是说它们可以转换成相同的类型

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>;