编辑
我想下面的代码会假设我有一个重载版本的addChild(),它接受一个已经包装在unique_ptr中的Sprite,其中拥有所有权是可以的。只是想在别人之前提一下。:) 我在非常漫长的一天后编写了所有的代码,所以请将其视为伪代码质量,仅用于展示手头的问题。
原始问题
我正在编写一个框架,其中包含显示列表、父/子等。我认为在这里使用例如unique_ptr<Sprite>
是正确的方式,因为当您向父显示对象添加一个子对象时,逻辑上只有父对象现在成为该子对象的唯一所有者。
然而,将有可用的方法,如getChildAt(index)
和getChildByName
等,我认为应该返回引用或指针值,因为这些方法只是用于将子项暴露给操作,而不是转移所有权。
最后,问题和这个问题的原因在于以下情况。让我们假设我们有两个Sprite
对象,它们都是显示列表根目录Stage
的子对象。假设我们有第三个子Sprite。
Stage newStage;
std::unique_ptr<Sprite> parentOne(new Sprite);
std::unique_ptr<Sprite> parentTwo(new Sprite);
newStage.addChild(parentOne); //Stage takes ownership of parentOne
newStage.addChild(parentTwo); //Stage takes ownership of parentTwo
std::unique_ptr<Sprite> someChild(new Sprite);
parentOne->addChild(someChild) //parentOne takes ownership of someChild.
现在,假设在使用这个框架的游戏或其他代码库的某个地方,通过getChildAt(int index);
方法访问someChild
。
Sprite& child = parentOne->getChildAt(0);
以下的情况是完全合法的:
parentTwo->addChild(child);
addChild
方法会处理将子项从其先前的父项中移除(如果存在父项),以便新的父项现在可以使该子项成为其显示列表部分的一部分。我将每个精灵的子项作为引用或指针返回,因为我们不想在方法(如
getChildAt()
)中交出所有权,只是提供对子项的访问。我们不想将其作为unique_ptr
交出,并使其超出范围并死亡。但是,正如我所说,现在可以将此子项(现在通过引用或指针访问)传递给另一个容器(假设在拖放操作中,从一个列表中拖动项目到另一个列表中)。我们现在面临的问题是,唯一所有权需要从一个父项转移到另一个父项,但我们只有一个引用或原始指针。
我想知道这个问题的合理解决方案是什么。如果我返回一个指针,是否可能在这个阶段正确地转移所有权?
void Sprite::addChild(Sprite* newChildToOwn)
{
/* by checking newChildToOwn->parent we can see that the child is already owned
by someone else. We need to not only remove the child from that parents' part of the
display list and add it here, but transfer exclusive object ownership of newChildToOwn
to this->.
*/
}
moveChild
或takeChild
,并确保它以move
的方式接收其参数(可以使用右值引用或unique_ptr
)。 - Yakk - Adam Nevraumont