我试图了解双重调度是如何工作的。我创建了一个从抽象类 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 许可协议
好吧,很明显,你真的没有
fightwho
在你的Creature
类中声明,所以你需要在那里声明它,并将它声明为virtual
。双重调度的工作方式是调用(假设
Warrior& w = ...
,而不是Warrior w
):First the virtual mechanism will chose
Warrior::fight
instead ofMonster::fight
and then the overloading mechanism will pickMonster::fightwho(Warrior& m)
instead ofWarrior::fightwho(Warrior& m)
.请注意,如果您有以下内容会更有意义:因此,最终将被调用的方法将根据您调用它的对象的类型和作为参数发送的对象的类型进行分派,即 双重分派
此外,请注意,这可能不是最好的示例,因为您的类型是同一层次结构的成员。访问者设计模式是在不支持它作为一等公民的语言中双重分派实现的一个很好的例子(即 C++ 和衍生品:Java、C#…)
正如@CrazyCasta 正确指出的那样,当您的类层次结构开始增长时,这种方法变得更加难以维护并且可能导致方法数量激增,因此请谨慎选择……