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);
4条答案
按热度按时间wj8zmpe11#
多分派是根据传递给函数调用的参数的运行时类型来选择要调用的函数版本的能力。
下面是一个在C++中无法正常工作的示例(未经测试):
r3i60tvu2#
多分派是指执行的函数依赖于多个对象的运行时类型。
C++有单调度,因为当你使用虚函数时,实际运行的函数只依赖于-〉或.运算符左边的对象的运行时类型。
我很难想出一个真实的的多分派编程案例,也许是在一个不同角色互相战斗的游戏中。
战斗的赢家可能取决于双方的特征,因此您可能希望将此调用调度到以下对象之一,具体取决于两个参数的运行时类型:
函数的作用取决于两个参数的类型,而不仅仅是一个参数。在C++中,你可能需要把它写成一些虚函数。虚函数的选择取决于一个参数(this指针)。然后,虚函数可能需要包含一个开关或一些东西来对另一个参数做一些特殊的事情。
7ajki6be3#
在 single dispatch 中,执行的函数仅取决于对象类型。在 double dispatch 中,执行的函数取决于对象类型和一个参数。
在以下示例中,使用单调度调用函数
Area()
,而Intersect()
依赖于双调度,因为它采用Shape参数。本示例基于此article。
lkaoscv74#
展望2022年,在C中有很多技术可以实现多分派
这是一个动态转换(在本文发布时已经可用):https://gist.github.com/jspahrsummers/0834f93cac6d5efa2418ddddf7244b16
这是最近的元程序设计:https://arne-mertz.de/2019/10/multiple-dispatch-over-covariant-functions/
如果你把它和julia或者类似的东西比较一下,它会更复杂,而且可能会有一些性能开销(具体多少有待澄清),这可能会根据C编译器的不同而有所不同,最终julia的LLVM也会使用某种形式的RTTI。
不确定在最新和最好的C++20中是否可以做得更好。