在这段代码中:
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 *’转换为’LeftSide *’_
我认为(我看错了)我可以将指针从派生分配到基础而没有任何问题.那问题出在哪里?
解决方法
问题不在于从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 }