为什么我需要转换?

问题描述:

在此代码:为什么我需要转换?

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 *' 到 '莱夫特赛德*' _

我我认为(错误,因为我看到),我可以分配指针从派生到基地没有任何问题。那么问题在哪里?

问题不是同来自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

我觉得呢? :运营商要求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

你想同时分支返回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

这两个应该是相同的类型,或者一个应该可以转换到另一个。

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