我想了解多次发送是什么。我阅读了很多不同的文本,但我仍然不知道多重发送是什么以及它有什么好处。也许我缺少的是使用多个调度的代码片段。请问,您是否可以使用多个调度在C ++中编写一小段代码,以便我可以看到它无法正确编译/运行,因为C ++只有单个调度?我需要看到差异。感谢。
答案 0 :(得分:64)
Multi-dispatch是根据传递给函数调用的参数的运行时类型选择要调用的函数版本的能力。
这是一个在C ++中无法正常工作的示例(未经测试):
class A { };
class B : public A { };
class C : public A { }
class Foo
{
virtual void MyFn(A* arg1, A* arg2) { printf("A,A\n"); }
virtual void MyFn(B* arg1, B* arg2) { printf("B,B\n"); }
virtual void MyFn(C* arg1, B* arg2) { printf("C,B\n"); }
virtual void MyFn(B* arg1, C* arg2) { printf("B,C\n"); }
virtual void MyFn(C* arg1, C* arg2) { printf("C,C\n"); }
};
void CallMyFn(A* arg1, A* arg2)
{
// ideally, with multi-dispatch, at this point the correct MyFn()
// would be called, based on the RUNTIME type of arg1 and arg2
pFoo->MyFn(arg1, arg2);
}
...
A* arg1 = new B();
A* arg2 = new C();
// Using multi-dispatch this would print "B,C"... but because C++ only
// uses single-dispatch it will print out "A,A"
CallMyFn(arg1, arg2);
答案 1 :(得分:19)
多次调度是指执行的函数取决于多个对象的运行时类型。
C ++具有单一调度,因为当您使用虚函数时,运行的实际函数仅取决于 - >左侧对象的运行时类型。要么 。操作
我很难想到一个真正的多重调度编程案例。也许在各种角色互相争斗的游戏中。
void Fight(Opponent& opponent1, Opponent& opponent2);
战斗的胜利者可能取决于两个对手的特征,因此您可能希望此调用分派到以下之一,具体取决于两个参数的运行时类型:
void Fight(Elephant& elephant, Mouse& mouse)
{
mouse.Scare(elephant);
}
void Fight(Ninja& ninja, Mouse& mouse)
{
ninja.KarateChop(mouse);
}
void Fight(Cat& cat, Mouse& mouse)
{
cat.Catch(mouse);
}
void Fight(Ninja& ninja, Elephant& elephant)
{
elephant.Trample(ninja);
}
// Etc.
该函数的作用取决于两个参数的类型,而不仅仅是一个。在C ++中,您可能必须将其编写为一些虚函数。将根据一个参数(this指针)选择虚函数。然后,虚函数可能需要包含一个开关或其他东西,以执行另一个参数特定的操作。
答案 2 :(得分:11)
参见B. Stroustrup撰写的这篇论文:Open Multi-Methods for C++
答案 3 :(得分:3)
在单一调度中,执行的功能仅取决于对象类型。在 double dispatch 执行的函数取决于对象类型和a 参数。
在以下示例中,使用调用函数Area()
单一调度,而Intersect()
依赖于双重调度,因为它需要一个
形状参数。
class Circle;
class Rectangle;
class Shape
{
virtual double Area() = 0; // Single dispatch
// ...
virtual double Intersect(const Shape& s) = 0; // double dispatch, take a Shape argument
virtual double Intersect(const Circle& s) = 0;
virtual double Intersect(const Rectangle& s) = 0;
};
struct Circle : public Shape
{
virtual double Area() { return /* pi*r*r */; }
virtual double Intersect(const Shape& s);
{ return s.Intersect(*this) ; }
virtual double Intersect(const Circle& s);
{ /*circle-circle*/ }
virtual double Intersect(const Rectangle& s);
{ /*circle-rectangle*/ }
};
该示例基于此article。