C++ 中的双重调度/多方法
我有一个关于 C++ 双重调度的问题。 在下面的代码中,我希望第二组的结果与第一组的结果匹配。
我不知道实际类型(除非我尝试dynamic_cast),但我确实知道该对象是从 BaseClass 类型继承的。 实现这一目标的最有效(性能方面)的方法是什么?
在谷歌搜索了一段时间后,我发现了双重调度和洛基多重方法。 Shape 示例的问题是,在我的应用程序中,Processor 和 BaseClass 是完全独立的,并且没有可以相互调用的通用方法。 其次,只有一个处理器(即没有任何东西继承自它)。
谢谢你的帮助。
#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;
}
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.
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?
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).
Thanks for any help.
#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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您错过了双重调度的“双重”部分。
此模式的要点是确保调用处理器的正确方法 - 接受正确类型的方法。 由于处理器最初不知道传递给它的对象的类型,因此您需要对象来告诉处理器它的类型是什么。
本质上,每个对象都需要一个虚拟的
processMe(Processor &p)
方法,处理器调用它。processMe
的实现调用p.processObject(this)
。 但这一次,“这个”有一个已知的类型! 因此,您最终会得到正确的proceessObject
,而不是无限递归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.
In essence, each object needs a virtual
processMe(Processor &p)
method, and the processor calls it. The implementation ofprocessMe
callsp.processObject(this)
. But this time around, "this" has a known type! So instead of infinite recursion, you end up with the rightproceessObject
called您必须在 BaseClass 上放置一个虚拟方法才能从派生类调用 processObj。
您基本上需要访客模式,但只有一种类型的访客。 您可能会为自己节省一些未来的精力,将 Processor 变成一个抽象类并实现一个具体的 ProcessorImpl 类,从而使将来添加另一个处理器类变得微不足道,或者您可以等到这种情况出现并暂时保持原样。
You'll have to put a virtual method on BaseClass to call processObj from the derived classes.
You basically want the Visitor pattern, but with only one type of visitor. You might save yourself some future effort and make Processor into an abstract class and implement the one concrete ProcessorImpl class, making it trivial to add another processor class in the future, or you could wait until that situation comes up and leave things as is for now.
访客模式就是为了处理这种情况而设计的。
The Visitor Pattern is designed just for handling this sort of situation.
太感谢了。 这解决了我的问题,我明白了双重调度的含义! 这是后代的完整代码(请有人教我如何正确格式化):
Thank you so much. This solved my problem and I understand what double dispatch means! Here is the complete code for posterity (somebody please teach me how to get the formatting right):