インターフェイス ポインターとインターフェイス
インターフェイス実装のインスタンスは、実際にはメソッドへのポインターの配列へのポインターです。つまり、インターフェイスで指定されたすべてのメソッドの実装を参照する関数テーブルです。 複数のインターフェイスを持つオブジェクトは、複数の関数テーブルへのポインターを提供できます。 配列にアクセスできるポインターを持つコードは、そのインターフェイス内のメソッドを呼び出すことができます。
この複数の間接参照について正確に言うと不便なので、代わりに、別のオブジェクトがそのメソッドを呼び出すために必要なインターフェイス関数テーブルへのポインターは、単に インターフェイス ポインター呼び出されます。 関数テーブルは、C アプリケーションで手動で作成することも、Visual C++ (または COM をサポートする他のオブジェクト指向言語) を使用してほぼ自動的に作成することもできます。
適切なコンパイラ サポート (C および C++ に固有) では、クライアントは、配列内の位置ではなく、名前を使用してインターフェイス メソッドを呼び出すことができます。 インターフェイスは型であるため、コンパイラはメソッドの名前を指定して、各インターフェイス メソッド呼び出しのパラメーターの型と戻り値を確認できます。 これに対し、クライアントが位置ベースの呼び出しスキームを使用している場合、C または C++ であっても、このような型チェックは使用できません。
各インターフェイスは、メソッドの機能グループの不変コントラクトです。 実行時に、グローバル一意インターフェイス識別子 (IID) を使用してインターフェイスを参照します。 COM でサポートされているグローバル一意識別子 (GUID) の特定のインスタンスであるこの IID を使用すると、クライアントは、不要なオーバーヘッドを発生させることなく、同じ名前の同じインターフェイスの複数のバージョンを持つことからシステムで発生する可能性のある混乱なしに、インターフェイスのセマンティクスをサポートするかどうかをオブジェクトに正確に要求できます。
要約すると、COM インターフェイスとは何かを理解することが重要であり、次のものではありません。
- COM インターフェイスは C++ クラスと同じではありません。 純粋な仮想定義には実装がありません。 C++ プログラマの場合は、インターフェイスの実装をクラスとして定義できますが、これは、COM が指定しない実装の詳細の見出しの下にあります。 インターフェイスを実際に存在させるには、インターフェイスを実装するオブジェクトのインスタンスを作成する必要があります。 さらに、動作がインターフェイス定義に準拠している限り、異なるオブジェクト クラスが異なる方法でインターフェイスを実装しても、バイナリ形式で同じ意味で使用できます。
- COM インターフェイスはオブジェクトではありません。 これは単に関連する関数のグループであり、クライアントとオブジェクトが通信するバイナリ標準です。 インターフェイス メソッドへのポインターを提供できる限り、オブジェクトは任意の内部状態表現を持つ任意の言語で実装できます。
- COM インターフェイスは厳密に型指定されています。 すべてのインターフェイスには独自のインターフェイス識別子 (GUID) があり、他の名前付けスキームで重複が発生する可能性がなくなります。
- COM インターフェイスは不変です。 古いインターフェイスの新しいバージョンを定義して、同じ識別子を指定することはできません。 インターフェイスのメソッドを追加または削除したり、セマンティクスを変更したりすると、古いインターフェイスの新しいバージョンではなく、新しいインターフェイスが作成されます。 そのため、新しいインターフェイスは古いインターフェイスと競合できません。 ただし、オブジェクトは複数のインターフェイスを同時にサポートでき、異なる識別子を持つインターフェイスの連続するリビジョンであるインターフェイスを公開できます。 したがって、各インターフェイスは個別のコントラクトであり、システム全体のオブジェクトは、呼び出しているインターフェイスのバージョンが想定されるインターフェイスであるかどうかを心配する必要はありません。 インターフェイス ID (IID) は、インターフェイス コントラクトを明示的かつ一意に定義します。
関連トピック