C++ 中的双重调度/多方法
我有一个关于 C++ 双重调度的问题.在下面的代码中,我希望第二组的结果与第一组的结果相匹配.
I have a question on C++ double dispatch. In the code below, I want the results from the second set to match the results from the first set.
我不知道实际类型(除非我尝试使用 dynamic_cast),但我知道该对象是从 BaseClass 类型继承的.实现此目标的最有效(在性能方面)的方法是什么?
I don't know the actual type (unless I try dynamic_cast) but I do know that the object inherited from the BaseClass type. What is the most efficient (performance-wise) way to accomplish this?
在谷歌上搜索了一段时间后,我发现了双重调度和 loki 多方法.我在 Shape 示例中遇到的问题是,在我的应用程序中,Processor 和 BaseClass 是完全独立的,并且没有它们可以相互调用的通用方法.其次,只有一个处理器(即没有任何继承自它).
After googling around for a while I found out about double dispatch and the loki multimethods. The problem I have with the Shape examples is that in my application, Processor and BaseClass are entirely independent and don't have a common method that they can call in each other. Secondly, there is only one Processor (i.e. nothing inherits from it).
感谢您的帮助.
#include <iostream>
#include <string>
using namespace std;
class BaseClass{
public:
BaseClass(){}
virtual void myFunction(){cout << "base myFunction called" << endl;}
};
class Derived1: public BaseClass{
public:
Derived1():BaseClass(){}
void myFunction(){cout << "Derived1 myFunction called" << endl;}
};
class Derived2: public BaseClass{
public:
Derived2():BaseClass(){}
void myFunction(){cout << "Derived2 myFunction called" << endl;}
};
class Derived3: public BaseClass{
public:
Derived3():BaseClass(){}
void myFunction(){cout << "Derived3 myFunction called" << endl;}
};
class Processor{
public:
Processor(){}
virtual void processObj(BaseClass* bc){cout << "got a base object" << endl; bc->myFunction();}
virtual void processObj(Derived1* d1){cout << "got a derived1 object" << endl; d1->myFunction();}
virtual void processObj(Derived2* d2){cout << "got a derived2 object" << endl; d2->myFunction(); }
};
int main() {
BaseClass *bcp=new BaseClass();
Derived1 *dc1p=new Derived1();
Derived2 *dc2p=new Derived2();
Derived3 *dc3p=new Derived3();
Processor p;//can also use Processor* p = new Processor()
//first set results
p.processObj(bcp);
p.processObj(dc1p);
p.processObj(dc2p);
p.processObj(dc3p);
BaseClass *bcp1=bcp;
BaseClass *dc1p1=dc1p;
BaseClass *dc2p1=dc2p;
BaseClass *dc3p1=dc3p;
//second set results
p.processObj(bcp1);
p.processObj(dc1p1);
p.processObj(dc2p1);
p.processObj(dc3p1);
return 0;
}
推荐答案
您错过了双重派遣的双重"部分.
You missed the "double" part of the double dispatch.
此模式的重点是确保调用处理器的正确方法 - 接受正确类型的方法.由于处理器最初不知道传递给它的对象的类型,因此您需要对象告诉处理器它的类型是什么.
The point of this pattern is to make sure that the right method of the processor is called - the method that accepts the right type. Since the processor is initially not aware of the type of the object that's passed to it, you need the object to tell the processor what its type is.
本质上,每个对象都需要一个虚拟的processMe(Processor &p)
方法,处理器调用它.processMe
的实现调用了 p.processObject(this)
.但这一次,this"有一个已知类型!所以不是无限递归,你最终得到了正确的 processObject
调用
In essence, each object needs a virtual processMe(Processor &p)
method, and the processor calls it. The implementation of processMe
calls p.processObject(this)
. But this time around, "this" has a known type! So instead of infinite recursion, you end up with the right proceessObject
called
相关文章