了解双重调度 C

新手上路,请多包涵

我试图了解双重调度是如何工作的。我创建了一个从抽象类 Creature 派生的怪物和战士可以战斗的示例。类 Creature 有方法“fight”,它在派生类中定义,并且在每个派生类中定义了如果战士与战士或怪物等战斗会发生什么。我编写了以下代码:

 #include<iostream>
using namespace std;

class Monster;
class Warrior;

class Creature{
public:
    virtual void fight(Creature&) =0;
};

class Monster: public Creature{
    void fightwho(Warrior& w) {cout<<"Monster versus Warrior"<<endl; }
    void fightwho(Monster& m) {cout<<"Monster versus Monster"<<endl; }
public:
    void fight(Creature& c)  {c.fightwho(*this);}
};

class Warrior: public Creature{
    void fightwho(Warrior& w) {cout<<"Warrior versus Warrior"<<endl; }
    void fightwho(Monster& m) {cout<<"Monster versus Warrior"<<endl; }
public:
    void fight(Creature& c) {c.fightwho(*this);}
};

int main()
{
Warrior w;
Monster m;
w.fight(m);
}

这会导致编译器错误,我预见到:

ex12_10.cpp:在成员函数’virtual void Monster::fight(Creature&)‘中:ex12_10.cpp:17:30:错误:’class Creature’没有名为’fightwho’的成员

ex12_10.cpp:在成员函数’virtual void Warrior::fight(Creature&)‘中:ex12_10.cpp:24:29:错误:’class Creature’没有名为’fightwho’的成员

但我不知道如何从这里开始……请帮忙。

原文由 gartenzwerg 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 918
2 个回答

好吧,很明显,你真的没有 fightwho 在你的 Creature 类中声明,所以你需要在那里声明它,并将它声明为 virtual

双重调度的工作方式是调用(假设 Warrior& w = ... ,而不是 Warrior w ):

 w.fight(m);

First the virtual mechanism will chose Warrior::fight instead of Monster::fight and then the overloading mechanism will pick Monster::fightwho(Warrior& m) instead of Warrior::fightwho(Warrior& m) .请注意,如果您有以下内容会更有意义:

 Warrior w;
Monster m;
Creature& c1 = w;
Creature& c2 = m;
c1.fight(c2); // not w.fight(m)

因此,最终将被调用的方法将根据您调用它的对象的类型和作为参数发送的对象的类型进行分派,即 双重分派

此外,请注意,这可能不是最好的示例,因为您的类型是同一层次结构的成员。访问者设计模式是在不支持它作为一等公民的语言中双重分派实现的一个很好的例子(即 C++ 和衍生品:Java、C#…)

正如@CrazyCasta 正确指出的那样,当您的类层次结构开始增长时,这种方法变得更加难以维护并且可能导致方法数量激增,因此请谨慎选择……

原文由 Zdeslav Vojkovic 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果你想这样做,你将需要使用 RTTI。你需要检查传入的东西的类型。一般来说,如果你可以避免的话,这不是最好的设计模式。如果要与两个对象交互,通常需要使用另一个对象的标准接口。例如,您可能会说 bio.attack(other_creature) 和 attack 可能会查询另一个生物的防御,并基于此和它自己的统计信息发布对 other_creature 的 hp 更新。

原文由 CrazyCasta 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题