【发布时间】:2009-11-23 15:32:22
【问题描述】:
所以,我有一个基类指针列表:
list<Base*> stuff;
然后,在某个时候,其中一个对象将查看所有其他对象。
Base * obj = ...; // A pointer from the 'stuff'-list.
for (list<Base*>::iterator it = stuff.begin(); it != stuff.end(); it++)
{
if (obj == *it)
continue;
// Problem scenario is here
obj->interact(it);
}
我想要实现的是,根据派生类型obj 和*it 的不同,它们之间的交互方式会有所不同,即DerivedA 在与DerivedB 交互时会自行销毁,但前提是DerivedB 已设置属性 bool c = true;。所以像:
struct Base
{
virtual void interact(Base * b); // is always called
};
struct DerivedA : public Base
{
virtual void interact(Base * b){} // is never called
virtual void interact(DerivedB * b) // is never called
{
if (b->c)
delete this;
}
};
struct DerivedB : public Base
{
bool c = false;
virtual void interact(Base * b){} // is never called
virtual void interact(DerivedA * a) // is never called
{
c = true;
}
};
// and many many more Derived classes with many many more specific behaviors.
在编译时,它们都是Base-pointers 并且不能互相调用并期望类型神奇地出现。如果这是一种单向关系,即我知道其中一种是什么类型,我可以使用Visitor pattern。我相信我应该使用某种Mediator pattern,但无法真正弄清楚如何因为调解员也将持有Base-pointers,因此它不会有所作为。
我不知道如何继续……有人吗?
背景:
我正在创建一个游戏,这个问题源于 Room 类,他们跟踪它的内容,即 GameObjects 当前在房间里的内容。
有时,一个物体会移动(例如,玩家)。然后房间将遍历即将移动的地砖上的所有对象(上面的循环),并检查对象是否会相互交互。
例如,如果它是Troll,Player 会想要伤害它。或者他只是想伤害来自任何另一个“团队”(可以从函数getAlignment()访问,所有@ 987654343@实现)。
【问题讨论】:
-
你想知道背景故事,因为我可能从错误的方向来处理这个问题?
-
正确。通常继承用于解耦,当您处理具有特殊情况的对象时,您会遇到这种情况。一般来说,如果我们了解大局,我们可以更好地回答:)
-
我添加了一些澄清代码以及背景故事,希望它能澄清问题。
-
在实际系统中,
Base::interact()是否被标记为虚拟? -
您正在寻找的是所谓的“双重派遣”或“多重派遣”。它在某些语言中原生存在(例如,带有“多方法”的 Common Lisp),但就像几乎所有其他语言一样,可以将其入侵到 C++ 中。
标签: c++ design-patterns inheritance multiple-dispatch