Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
409 views
in Technique[技术] by (71.8m points)

design patterns - Double dispatch/multimethods in 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.

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;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...