我试图了解双重调度的工作原理。我创建了一个示例,其中抽象类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”的成员
但我不知道如何从这里继续...请帮助。
最佳答案
好吧,显然,您确实没有在fightwho
类中声明Creature
,因此您需要在此声明它,并将其声明为virtual
。
双调度以一种用于调用的方式工作(这假定Warrior& w = ...
,而不是Warrior w
):
w.fight(m);
首先,虚拟机制将选择
Warrior::fight
而不是Monster::fight
,然后重载机制将选择Monster::fightwho(Warrior& m)
而不是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正确指出的那样,当您的类层次结构开始增长时,这种方法变得难以维护,并且可能导致方法数量激增,因此请谨慎选择...
关于c++ - 了解双重调度C++,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12582040/