【发布时间】:2021-01-27 23:02:09
【问题描述】:
假设我有一个模板化的Array<T> 结构,我想从T * 的一种指针类型转换为另一种。具体来说,我有一个返回Array<Entity *> 的函数,我想将其转换为Array<Player *>:
Array<Entity *> get_player_entities();
Array<Player *> players = (Array<Player *>)get_player_entities();
请注意,Player 扩展了 Entity。因为指针具有相同的大小,这应该没问题!但我收到以下错误:
error C2440: 'type cast' : cannot convert from 'Array<Entity *>' to 'Array<Player *>'; No constructor could take the source type, or constructor overload resolution was ambiguous
所以我可以做以下,但是有点麻烦:
Array<Entity *> temp = get_player_entities();
Array<Player *> players = *(Array<Player *> *)&temp;
想知道是否有更简单的方法来解决这个问题?为什么不允许这样做?不应该将一种指针类型转换为另一种类型总是有效吗?例如,在非模板世界中,您始终可以在不同的指针类型之间进行转换。
理想情况下,我希望解决方案不涉及额外的模板。例如,我知道我可以将 get_player_entities 方法更改为模板化。
【问题讨论】:
-
不应该将一种指针类型转换为另一种类型总是有效吗? 除了某些边缘情况(如转换成员函数指针或转换函数指针),通常将一种数据指针类型转换为另一种指针类型要么有效,要么是未定义的行为。第一种情况,强制转换不是强制转换指针类型,所以这个问题无关紧要。第二种情况,它是未定义的行为,所以任何事情都可能发生。
-
你这个有点麻烦的解决方案是可怕的。如果您要点亮一个包含转换后的指针的新容器,请使用
std::transform或类似名称。无论如何,您都会受到制作容器副本的影响。关于您的问题,“不应该将一种指针类型转换为另一种类型总是有效”不,它不应该,而且它没有。 -
这与大小无关;这是关于语义的。指向基址的指针与指向派生的指针具有不同的操作集。在某些情况下,其中一种类型的对象可以转换为另一种,但没有大锤总是强制转换。
-
由于
Array是您自己的类型,您可以考虑添加一个函数来进行转换:template <class T> T* to_type(int idx) { return (T*)(*this)[index]); }。您可以使用显式类型调用它:my_array.to_type<Player>(3);。