インターフェイス ポインターとインターフェイス

インターフェイス実装のインスタンスは、実際にはメソッドへのポインターの配列へのポインターです。つまり、インターフェイスで指定されたすべてのメソッドの実装を参照する関数テーブルです。 複数のインターフェイスを持つオブジェクトは、複数の関数テーブルへのポインターを提供できます。 配列にアクセスできるポインターを持つコードは、そのインターフェイス内のメソッドを呼び出すことができます。

この複数の間接参照について正確に言うと不便なので、代わりに、別のオブジェクトがそのメソッドを呼び出すために必要なインターフェイス関数テーブルへのポインターは、単にインターフェイス ポインターと呼ばれます。 関数テーブルは、C アプリケーションで手動で作成することも、Visual C++ (または COM をサポートする他のオブジェクト指向言語) を使用してほぼ自動的に作成することもできます。

適切なコンパイラ サポート (C および C++ に固有のもの) を使用すると、クライアントは配列内の位置ではなく、名前を使用してインターフェイス メソッドを呼び出すことができます。 インターフェイスは型であるため、メソッドの名前を指定すると、コンパイラはパラメータの型と各インターフェイス メソッド呼び出しの戻り値をチェックできます。 これに対し、クライアントが位置ベースの呼び出しスキームを使用する場合、C または C++ であっても、このような型チェックは使用できません。

各インターフェイスは、メソッドの機能グループの不変コントラクトです。 実行時に、グローバル一意インターフェイス識別子 (IID) を使用してインターフェイスを参照します。 この IID は、COM でサポートされるグローバル一意識別子 (GUID) の特定のインスタンスであり、クライアントは、不必要なオーバーヘッドやシステム内で発生する可能性のある混乱を招くことなく、インターフェイスのセマンティクスをサポートしているかどうかをオブジェクトに正確に問い合わせることができます。同じ名前を持つ同じインターフェイスの複数のバージョンが存在しないようにします。

要約すると、COM インターフェイスとは何か、そしてそうでないものを理解することが重要です。

  • COM インターフェイスは C++ クラスと同じではありません。 純粋な仮想定義には実装がありません。 C++ プログラマーの場合は、インターフェイスの実装をクラスとして定義できますが、これは実装の詳細の見出しに該当し、COM では指定されません。 インターフェイスを実際に存在させるには、インターフェイスを実装するオブジェクトのインスタンスを作成する必要があります。 さらに、異なるオブジェクト クラスは、動作がインターフェイス定義に準拠している限り、異なる方法でインターフェイスを実装しても、バイナリ形式で互換的に使用できます。
  • COM インターフェイスはオブジェクトではありません。 これは単に関連する関数のグループであり、クライアントとオブジェクトが通信するバイナリ標準です。 インターフェイス メソッドへのポインターを提供できる限り、オブジェクトは任意の内部状態表現を持つ任意の言語で実装できます。
  • COM インターフェイスは厳密に型指定されています。 すべてのインターフェイスには独自のインターフェイス識別子 (GUID) があり、他の名前付けスキームで発生する可能性のある重複の可能性が排除されます。
  • COM インターフェイスは不変です。 古いインターフェイスの新しいバージョンを定義して、同じ識別子を指定することはできません。 インターフェイスのメソッドを追加または削除したり、セマンティクスを変更すると、古いインターフェイスの新しいバージョンではなく、新しいインターフェイスが作成されます。 したがって、新しいインターフェイスが古いインターフェイスと競合することはありません。 ただし、オブジェクトは複数のインターフェイスを同時にサポートでき、異なる識別子を持つインターフェイスの連続したリビジョンであるインターフェイスを公開できます。 したがって、各インターフェイスは別個のコントラクトであり、システム全体のオブジェクトは、呼び出しているインターフェイスのバージョンが予期したものであるかどうかを気にする必要はありません。 インターフェイス ID (IID) は、インターフェイス コントラクトを明示的かつ一意に定義します。

COM のオブジェクトとインターフェイス