それらは何ですか、それらの間の違いは何ですか?
ウィキペディアのような多くの情報源は、それらは同じものであると主張していますが、この質問のsbiのように、他の情報源は明示的に反対のことを言っています:
最初:「ビジターパターンは、C++でのダブルディスパッチをシミュレートする方法です。」これは、えーと、完全には正しくありません。実際、ダブルディスパッチはマルチディスパッチの1つの形式であり、C ++で(欠落している)マルチメソッドをシミュレートする方法です。
それらは同じです。
C ++で仮想メソッドを呼び出す場合、実行される実際のメソッドは、メソッドが呼び出されるオブジェクトの実行時型に基づいています。これは、単一の引数(この場合は暗黙の「this」引数)のタイプに依存するため、「単一ディスパッチ」と呼ばれます。したがって、たとえば、次のようになります。
class Base {
public:
virtual int Foo() { return 3; }
}
class Derived : public Base {
public:
virtual int Foo() { return 123; }
}
int main(int argc, char *argv[]) {
Base* base = new Derived;
cout << "The result is " << base->Foo();
delete base;
return 0;
}
実行すると、上記のプログラムは3ではなく123を出力します。これまでのところ良好です。
多重ディスパッチは、「this」ポインターのタイプとメソッドへの引数のタイプの両方でディスパッチする言語またはランタイムの機能です。考えてみてください(今のところC ++構文に固執しています):
class Derived;
class Base {
public:
virtual int Foo(Base *b) { cout << "Called Base::Foo with a Base*"; }
virtual int Foo(Derived *d) { cout << "Called Base::Foo with a Derived*"; }
}
class Derived : public Base {
public:
virtual int Foo(Base *b) { cout << "Called Derived::Foo with a Base*"; }
virtual int Foo(Derived *d) { cout << "Called Derived::Foo with a Derived*"; }
}
int main(int argc, char *argv[]) {
Base* base = new Derived;
Base* arg = new Derived;
base->Foo(arg);
delete base;
delete arg;
return 0;
}
C ++に多重ディスパッチがある場合、プログラムは「Called Derived :: Foo withaDervied*」を出力します。(残念ながら、C ++には多重ディスパッチがないため、プログラムは「Called Derived :: Foo with aBase *」を出力します。)
ダブルディスパッチはマルチディスパッチの特殊なケースであり、多くの場合エミュレートが容易ですが、言語機能としてはそれほど一般的ではありません。ほとんどの言語は、単一ディスパッチまたは複数ディスパッチのいずれかを実行します。