Objective-Cがすべてのメソッド呼び出しに動的バインディングを使用していることを私は知っています。これはどのように実装されますか?Objective-cはコンパイル前に「Cコードに変換」し、すべてに(void *)ポインターを使用しますか?
2 に答える
概念的には、ディスパッチャーライブラリ(一般にObjective Cランタイムと呼ばれます)があり、コンパイラーは次のように変換します。
[myObject myMethodWithArg:a andArg:b ];
の中へ
//Not exactly correct, but close enough for this
objc_msgSend(myObject, "myMethodWithArg:andArg:", a, b);
次に、ランタイムはすべてのバインディングとディスパッチを処理し、適切な関数を見つけて、それらの引数を使用して呼び出します。簡単に言えば、ハッシュルックアップのようなものと考えることができます。もちろん、実際よりもはるかに複雑です。
メソッドシグネチャなどに関連する問題は他にもたくさんあります(Cは型をエンコードしないため、ランタイムがそれを処理する必要があります)。
各ObjectiveCメソッドは、(事実上)C関数として「内部」で実装されます。メソッドにはメッセージ(テキスト文字列)が関連付けられており、クラスにはメッセージ文字列とC関数を照合するルックアップテーブルがあります。したがって、Objective Cメソッドを呼び出すと、実際に発生するのはメッセージ文字列をオブジェクトに送信し、オブジェクトはクラスのメソッドルックアップテーブルで関連するC関数を検索して実行します。
Objective Cには、オブジェクトが理解できないメッセージを転送して処理する方法、メッセージからメソッドへのルックアップをキャッシュする方法など、さらに多くの機能がありますが、それが基本です。
C ++も同様ですが、メッセージテーブルを持つクラスの代わりに、「vtable」と呼ばれるものがあり、テキスト文字列ではなく、vtableへのオフセットを介してメソッドを呼び出します。これは静的バインディングの形式であり、実行をいくらか高速化しますが、動的バインディングよりも柔軟性がありません。