9

C++ダブルディスパッチについて質問があります。以下のコードでは、2番目のセットの結果を最初のセットの結果と一致させたいと思います。

実際のタイプはわかりませんが(dynamic_castを試していない限り)、オブジェクトがBaseClassタイプから継承されていることはわかっています。これを達成するための最も効率的な(パフォーマンス面での)方法は何ですか?

しばらくグーグルした後、私はダブルディスパッチとロキマルチメソッドについて知りました。Shapeの例で私が抱えている問題は、私のアプリケーションでは、ProcessorとBaseClassが完全に独立しており、相互に呼び出すことができる共通のメソッドがないことです。次に、プロセッサは1つだけです(つまり、プロセッサから継承するものはありません)。

助けてくれてありがとう。

#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;
}
4

4 に答える 4

10

ダブル ディスパッチの「ダブル」部分を見逃しました。

このパターンのポイントは、プロセッサの正しいメソッド (正しい型を受け入れるメソッド) が呼び出されるようにすることです。プロセッサは、最初は渡されたオブジェクトの型を認識していないため、オブジェクトがその型をプロセッサに伝える必要があります。

基本的に、各オブジェクトには仮想processMe(Processor &p)メソッドが必要であり、プロセッサがそれを呼び出します。processMe呼び出しの実装p.processObject(this)。しかし今回は、"this" には既知の型があります。したがって、無限再帰の代わりに、右proceessObjectと呼ばれる権利になります

于 2009-01-09T21:53:41.950 に答える
6

Visitor パターンは、この種の状況を処理するためだけに設計されています。

于 2009-01-09T21:48:58.340 に答える
4

派生クラスから processObj を呼び出すには、BaseClass に仮想メソッドを配置する必要があります。

class BaseClass{
public:
       BaseClass(){}
       virtual void ProcessThis(Processor &p) { p.processObj(this); }
       virtual void myFunction(){cout << "base myFunction called" << endl;}
};

class Derived1: public BaseClass{
public:
       Derived1():BaseClass(){}
       void ProcessThis(Processor &p) { p.processObj(this); }
       void myFunction(){cout << "Derived1 myFunction called" << endl;}
};

class Derived2: public BaseClass{
public:
       Derived2():BaseClass(){}
       void ProcessThis(Processor &p) { p.processObj(this); }
       void myFunction(){cout << "Derived2 myFunction called" << endl;}
};

class Derived3: public BaseClass{
public:
       Derived3():BaseClass(){}
       void ProcessThis(Processor &p) { p.processObj(this); }
       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
   bcp->ProcessThis(p);
   dc1p->ProcessThis(p);
   dc1p->ProcessThis(p);
   dc3p->ProcessThis(p);

   BaseClass *bcp1=bcp;
   BaseClass *dc1p1=dc1p;   
   BaseClass *dc2p1=dc2p;
   BaseClass *dc3p1=dc3p;

   //second set results
   bcp1->ProcessThis(p);
   dc1p1->ProcessThis(p);
   dc2p1->ProcessThis(p);
   dc3p1->ProcessThis(p);

   Processor p2;
   bcp1->ProcessThis(p2);
   dc1p1->ProcessThis(p2);
   dc2p1->ProcessThis(p2);
   dc3p1->ProcessThis(p2);

   return 0;
}

基本的に Visitor パターンが必要ですが、訪問者のタイプは 1 つだけです。将来の労力を節約し、Processor を抽象クラスにして 1 つの具体的な ProcessorImpl クラスを実装し、将来別のプロセッサ クラスを簡単に追加できるようにするか、その状況が発生するまで待って、今のところそのままにしておくことができます。 .

于 2009-01-09T21:46:06.113 に答える
0

どうもありがとう。これで問題が解決し、二重発送の意味がわかりました! 後世の完全なコードは次のとおりです(誰かがフォーマットを正しくする方法を教えてください):

#include <iostream>
using namespace std;

class BaseClass;
class Derived1;
class Derived2;
class Derived3;

class Processor {
public:
       Processor(){}
       virtual void processObj(BaseClass* bc);
       virtual void processObj(Derived1* d1);
       virtual void processObj(Derived2* d2);
};


class BaseClass{
public:
       BaseClass(){}
       virtual void ProcessThis(Processor &p) { p.processObj(this); }
       virtual void myFunction(){cout << "base myFunction called" << endl;}
};

class Derived1: public BaseClass{
public:
       Derived1():BaseClass(){}
       void ProcessThis(Processor &p) { p.processObj(this); }
       void myFunction(){cout << "Derived1 myFunction called" << endl;}
};

class Derived2: public BaseClass{
public:
       Derived2():BaseClass(){}
       void ProcessThis(Processor &p) { p.processObj(this); }
       void myFunction(){cout << "Derived2 myFunction called" << endl;}
};

class Derived3: public BaseClass{
public:
       Derived3():BaseClass(){}
       void ProcessThis(Processor &p) { p.processObj(this); }
       void myFunction(){cout << "Derived3 myFunction called" << endl;}

};

void Processor::processObj(BaseClass* bc){cout << "got a base object" << endl; bc->myFunction();}
void Processor::processObj(Derived1* d1){cout << "got a derived1 object" << endl; d1->myFunction();}
void Processor::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

   bcp->ProcessThis(p);
   dc1p->ProcessThis(p);
   dc2p->ProcessThis(p);
   dc3p->ProcessThis(p);

   BaseClass *bcp1=bcp;
   BaseClass *dc1p1=dc1p;   
   BaseClass *dc2p1=dc2p;
   BaseClass *dc3p1=dc3p;

   //second set results

   bcp1->ProcessThis(p);
   dc1p1->ProcessThis(p);
   dc2p1->ProcessThis(p);
   dc3p1->ProcessThis(p);

   Processor p2;
   bcp1->ProcessThis(p2);
   dc1p1->ProcessThis(p2);
   dc2p1->ProcessThis(p2);
   dc3p1->ProcessThis(p2);

   return 0;
}
于 2009-01-09T22:25:09.327 に答える