class Animal
{
};
class Dog : public Animal
{
};
class Elephant : public Animal
{
};
有动物物品的集合:
std::vector<std::shared_ptr<Animal>> animals;
程序中的某处还有其他共享指针和弱指针,指的是“animals”集合中的对象。
例如,在动物的索引0处有Dog
个对象。
std::shared_ptr<Dog>& dog = std::static_pointer_cast<Dog>(animals[0]);
我需要将此对象的类型转换为Elephant
。我不能只删除这个对象(Dog
),并创建新的(Elephant
),因为弱指针将过期,而其他共享指针将引用旧对象,而不是新对象。
我需要这样做,弱指针和其他共享指针仍将引用相同的对象 - 但类型将是不同的(转换)。
所有引用均为Animal
类型,因此不会出现Dog
引用的情况,但它已经Elephant
。
我该怎么办?这种做法是否被认为是黑客攻击?
编辑(更多信息):
问题我在游戏中存在。对于游戏需求,我有时需要将动物转化为怪物,将怪物转化为NPC。 问题是有很多对不同演员的引用。例如,一些怪物可以选择另一个怪物的目标(因此怪物拥有指向另一个怪物的弱指针)。我给出的类层次结构只是示例,但对于真实它看起来像这样。演员 - &gt;怪物,动物,NPC,玩家
答案 0 :(得分:3)
您可以使用另一个间接级别来执行此操作:而不是直接使用Animal
,您可以创建以下内容:
class ShiftingAnimal
{
ShiftingAnimal(std::unique_ptr<Animal> animal){...}
void shift(std::unique_ptr<Animal> newAnimal){...}
}
并在整个程序中使用std::shared_ptr<ShiftingAnimal>
。
答案 1 :(得分:1)
您需要一个额外的间接层。创建一个拥有动物指针的包装器:
struct animal_wrapper {
std::unique_ptr<Animal> handle;
};
std::vector<std::shared_ptr<animal_wrapper>> animals;
现在您可以更改Wrapper::animal
指向的对象,指向该包装器的所有共享指针都将保持有效。
答案 2 :(得分:0)
在你的问题中你说:
程序中的某处还有其他共享指针和弱指针,指的是“animals”集合中的对象。
但似乎你不想要指向对象的指针,你想要的东西引用可能在不同时间包含不同对象的位置。
这是在其他答案中提出的,是实现目标的最通用方式;我认为没有理由编写新的类/结构。我建议使用std::vector<std::shared_ptr<std::unique_ptr<Animal>>>
,即一个共享指针向量,它引用可能在不同时间包含不同对象的位置(或者没有任何对象)。请注意,在两种情况下(plain unique_ptr和wrapper类),附加级别的间接为使用模式添加了一些“怪异”。 Here您可以找到显示这两个选项的代码。
另请注意,如果您开始使用unique_ptr而不仅仅是shared_ptr,则可能需要为Animal类提供虚拟析构函数(请参阅this other question)。
希望这有帮助。