発送とは?それは動的な解決を意味しますか?


8

私の知る限り、ディスパッチという用語は、単にメソッドの解決と呼び出しを意味します。静的でも動的でもかまいません。多くの人が静的ディスパッチ動的ディスパッチなどの用語を使用しているのを見ました。

私を混乱させるのは、いくつかの不可解な説明もあるということです。マルチディスパッチとは何かを理解しようとしていましたが、それはパラメータタイプによってサブプログラムを選択するだけのようです。私がそれを正しく理解していれば、静的マルチディスパッチ動的マルチディスパッチの両方が存在する可能性があり、C ++は無料の関数を介して複数のディスパッチを提供していると言えます。

しかし、複数のディスパッチに関するウィキペディアの記事によると、C ++には複数のパラメーターによる関数の動的解決がないため、C ++には複数のディスパッチはありません。そして、私はCommon Lispの例とC ++のオーバーロードされた関数との間の概念的な違いを本当に得ていません。マルチディスパッチという用語が動的ディスパッチを意味しない限り、私は概念的な違いを見つけることができないからです。そして、私は派遣が本当に何であるかを混乱させていることに気づきました

QAエントリのマルチディスパッチと関数のオーバーロードも確認しましたが、ディスパッチという用語は基本的に動的であることを前提としているようです。それも私を混乱させます。

ディスパッチという用語の正しい意味は何ですか?動的な解決を意味しますか?この用語は明確に定義されているのですか、それとも単なる従来のものですか?何が欠けていますか?


1
「複数のディスパッチに関するウィキペディアの記事では、C ++には複数のディスパッチがないと述べています」-どの記事を参照していますか?C ++には複数のディスパッチがあります。そしてはい、複数のディスパッチは動的を意味します(en.wikipedia.org/wiki/Multiple_dispatchを参照)
miraculixx

@miraculixxそれが記事です。ウィキペディアの記事では静的/動的属性について触れていないため、完全に混乱しました。
Eonil 2014年

1
@miraculixx-C ++には複数のディスパッチがありません。あなたはビジターパターンのようないくつかのデザインパターンでそれを偽造する必要があります。
David Hammen、2014年

@Davidは確かに、私はそこで混乱していたと思います。しばらくの間、関数のオーバーロード(C ++が静的に行う)とマルチディスパッチを混同していました。errare humanum EST ...
miraculixx

回答:


12

用語の意味は次のとおりです。

  • 静的ディスパッチ=ディスパッチの順序はコンパイル時に定義されます。これは単に、任意の関数/メソッド呼び出しが、まったく同じ関数を呼び出すfoo()か、またはx.foo()常に呼び出すことを意味します。これは一度確立された後、そのまま維持されます。これは、コンパイラがxコンパイル時にのタイプを判別できることを意味します。

  • 動的ディスパッチ=ディスパッチの順序は実行時に解決されます。これは、コンパイラがすべての関数/メソッドのルックアップテーブルを作成し、実行時に実際に呼び出す関数を決定することを意味します。クラスAとBがあり、どちらもメソッドXでインターフェースXを実装しているとしますX.bar()。実行時に、yが検査され、その実際のクラスに基づいて、A.bar()またはB.bar()呼び出されます。

  • 複数の動的ディスパッチ=ディスパッチの順序は、関数/メソッド名+引数のタイプ(=別名シグネチャ)に依存し、呼び出される実際の実装は、実行時に動的に決定されます。クラスAがメソッドA.fooBar(int)とを実装し、プログラムにA.fooBar(char *)への呼び出しがあるとa.fooBar(x)します。実行時の両方ax検査されると、コールへの実際の方法は、のタイプに基づいて決定されますx

動的ディスパッチ複数の動的ディスパッチの詳細については、Wikipediaを参照してください。


1
C ++フリー関数が静的マルチディスパッチをサポートしていることを処理できますか?
Eonil 2014年

まあ、当然のことながら、複数のディスパッチは動的です。c ++フリー関数では、コンパイラーはすべての作業を行います。コンパイラーは、常に関数名+シグニチャーを参照する静的ディスパッチであるすべての作業を行います。
miraculixx 2014年

1
ディスパッチという用語を静的と動的の両方で使用できる場合、複数のディスパッチが動的を意味するのはなぜですか?静的な複数のディスパッチについてはどうですか?
Eonil 2014年

1
静的ディスパッチとは、コンパイラーが、シグニチャーを含むすべての関数の参照テーブルを作成することを意味します。静的ディスパッチは事実上、複数のディスパッチであるため、慣例により、複数のディスパッチ担当者が動的であると想定していると見なされます。
miraculixx 2014年

@miraculixxすべての静的ディスパッチが複数ディスパッチであるとは限りません。これはC ++の場合ですが、一般的ではありません。
user253751 2015

12

ここでの私のアドバイスは、これを考えすぎないことです。ディスパッチとは単に送信することを意味します。イベントをリスナーにディスパッチし、割り込みをハンドラーにディスパッチし、メッセージをレシーバーにディスパッチし、呼び出しをプロシージャーまたは関数にディスパッチします。同じ基本概念のすべての側面。それを処理するコードにデータを送信します。解決とは、利用可能な宛先を選択することを意味し、ディスパッチの一部にすぎません。

コードの観点から見ると、ディスパッチはある種の情報のパケットとそれがどこに送信されるかを示す何かで始まり、パケットが送信(ディスパッチ)されたときに終了します。すべての言語には、ある種のディスパッチメカニズムが組み込まれていますが、多くの言語は、固有の目的に合わせて解決およびディスパッチスキームを実装しています。割り込み処理とウィンドウメッセージ処理が頭に浮かぶ例です。

C ++は静的または動的な解決を使用できますが、引数の型に基づいて関数を選択する場合は、コンパイル時にしか選択できません。Smalltalk / Objective CとRubyは、多くの動的言語と同様に、実行時にディスパッチを解決します。

単一のディスパッチとは、単一の引数がレシーバーと見なされ、呼び出されるメソッドを決定することを意味します。通常、メソッドはそのレシーバーオブジェクトのクラスにあり、メソッドシグネチャはそのクラスのディスパッチテーブル(vtable)のオフセットに変換されます。C ++の特権オブジェクトは、ドットの前のオブジェクトであり、「this」ポインターになります。

複数のディスパッチとは、特権のある受信側ではなく、通常、すべての引数タイプにわたるパターンマッチング操作を意味します。Common Lispオブジェクトシステムはこのアプローチを使用します。https://en.wikipedia.org/wiki/Multiple_dispatchを参照してください

オーバーロードされた演算子を持つC ++では、A + BとB + Aは異なるメソッドにディスパッチする必要があります。CLOSではそれらは同じにすることができます。

それ自体が複数のディスパッチではなく多要素解決であるため、おそらくマルチメソッドという用語を好むでしょう。http://c2.com/cgi/wiki?MultiMethodsを参照してください。またhttp://www.codeproject.com/Articles/242749/Multiple-dispatch-and-double-dispatch


1
「C ++は静的または動的な解決を使用できます...コンパイル時にのみ使用できます」、仮想メソッドはどうですか?これらは実行時に動的に決定され、メソッドシグネチャに依存します
miraculixx

うまくいけば、私の編集が私が意図したことをより明確にするでしょう。
david.pfx 2014年

0

C ++には複数の(動的)ディスパッチはありません。以下を検討してください。

#include <iostream>

struct Foo {
   virtual ~Foo() {}
};

struct FooOne : public Foo {};

struct Bar {
   virtual ~Bar() {}
   virtual void dispatch (const Foo &) {
      std::cout << "Bar::Dispatch(const Foo &)\n";
   }
};

struct BarOne : public Bar {
   using Bar::dispatch;
   virtual void dispatch (const Foo &) {
      std::cout << "BarOne::Dispatch(const Foo &)\n";
   }
   virtual void dispatch (const FooOne &) {
      std::cout << "BarOne::Dispatch(const FooOne &)\n";
   }
};

void process (Bar & bar, const Foo & foo) {
   bar.dispatch (foo);
}

int main () {
   Foo foo;
   Bar bar;
   FooOne foo_one;
   BarOne bar_one;

   process (bar, foo);
   process (bar, foo_one);

   process (bar_one, foo);
   process (bar_one, foo_one);

   bar_one.dispatch (foo_one);

   return 0;
}

上記の出力は

Bar::Dispatch(const Foo &)
Bar::Dispatch(const Foo &)
BarOne::Dispatch(const Foo &)
BarOne::Dispatch(const Foo &)
BarOne::Dispatch(const FooOne &)

内ではprocess(Foo& foo, const Bar& bar)、C ++はfooステートメントの引数に動的ディスパッチを使用しますfoo.dispatch(bar)。3番目と4番目の出力行は、このC ++スタイルの動的ディスパッチの動作を示しています。4番目の出力行は、C ++に複数のディスパッチがないことを示しています。その場合、その4番目の出力行は最後の行と同じになります。

その最後の行?それは静的ディスパッチです。コンパイラーは、コンパイル時に、呼び出す必要がある関数を正確に認識します。この最後の呼び出しは仮想テーブルを通過しません。


この例は有効で便利ですが、複数のディスパッチ、つまりマルチメソッドもさらに進んでいます。単一クラスのレシーバーにディスパッチする言語では、CLOSで自然に発生する種類の例を書くことさえできません。
david.pfx 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.