COM インターフェイスとは
C# または Java がわかっている場合、インターフェイスは使い慣れた概念である必要があります。 インターフェイスは、実装について何もディクテーションすることなく、オブジェクトがサポートできる一連のメソッドを定義 します 。 インターフェイスは、メソッドを呼び出すコードとメソッドを実装するコードの間の明確な境界をマークします。 コンピューター サイエンスの用語では、呼び出し元は実装から 切り離されます 。
C++ では、インターフェイスと最も近いものは純粋仮想クラスです。つまり、純粋仮想メソッドのみを含み、他のメンバーを含むクラスです。 インターフェイスの仮定の例を次に示します。
// The following is not actual COM.
// Pseudo-C++:
interface IDrawable
{
void Draw();
};
この例の考え方は、一部のグラフィックス ライブラリ内のオブジェクトのセットが描画可能であるという点です。 インターフェイスは IDrawable
、描画可能なオブジェクトがサポートする必要がある操作を定義します。 (慣例により、インターフェイス名は "I" で始まります)。この例では、インターフェイスは IDrawable
1 つの操作を定義します。 Draw
すべてのインターフェイスは 抽象であるため、プログラムはオブジェクトのインスタンスを IDrawable
作成できませんでした。 たとえば、次のコードはコンパイルされません。
IDrawable draw;
draw.Draw();
代わりに、グラフィックス ライブラリには、インターフェイスを 実装 するオブジェクトが IDrawable
用意されています。 たとえば、ライブラリは図形を描画するための図形オブジェクトと、イメージを描画するためのビットマップ オブジェクトを提供する場合があります。 C++ では、これは共通の抽象基本クラスから継承することによって行われます。
class Shape : public IDrawable
{
public:
virtual void Draw(); // Override Draw and provide implementation.
};
class Bitmap : public IDrawable
{
public:
virtual void Draw(); // Override Draw and provide implementation.
};
クラスとクラスBitmap
はShape
、2 種類の描画可能なオブジェクトを定義します。 各クラスは、メソッドを IDrawable
継承し、独自の実装を Draw
提供します。 当然、2 つの実装は大きく異なる場合があります。 たとえば、このメソッドは Shape::Draw
一連の線をラスター化し Bitmap::Draw
、ピクセルの配列を blit する場合があります。
このグラフィックス ライブラリを使用するプログラムは、直接またはポインターを使用するのではなく、ポインターを使用してIDrawable
Shape
オブジェクトをBitmap
操作Shape
Bitmap
します。
IDrawable *pDrawable = CreateTriangleShape();
if (pDrawable)
{
pDrawable->Draw();
}
ポインターの配列 IDrawable
をループする例を次に示します。 配列内の各オブジェクトが継承 IDrawable
している限り、配列にはさまざまな図形、ビットマップ、およびその他のグラフィックス オブジェクトが含まれる場合があります。
void DrawSomeShapes(IDrawable **drawableArray, size_t count)
{
for (size_t i = 0; i < count; i++)
{
drawableArray[i]->Draw();
}
}
COM の重要なポイントは、呼び出し元のコードが派生クラスの型を見ないということです。 つまり、型 Shape
の変数や Bitmap
コードで宣言することはありません。 図形とビットマップに対するすべての操作は、ポインターを使用して IDrawable
実行されます。 このように、COM はインターフェイスと実装の間で厳密な分離を維持します。 およびクラスの実装のShape
Bitmap
詳細は、バグの修正や新機能の追加など、呼び出し元のコードに変更を加えずに変更される可能性があります。
C++ 実装では、インターフェイスはクラスまたは構造体を使用して宣言されます。
注意
このトピックのコード例は、実際のプラクティスではなく、一般的な概念を伝えるために用意されています。 新しい COM インターフェイスの定義は、このシリーズの範囲外ですが、ヘッダー ファイルでインターフェイスを直接定義することはできません。 代わりに、COM インターフェイスは、インターフェイス定義言語 (IDL) と呼ばれる言語を使用して定義されます。 IDL ファイルは、C++ ヘッダー ファイルを生成する IDL コンパイラによって処理されます。
class IDrawable
{
public:
virtual void Draw() = 0;
};
COM を使用する場合は、インターフェイスがオブジェクトではないことに注意することが重要です。 これらは、オブジェクトが実装する必要があるメソッドのコレクションです。 いくつかのオブジェクトは、次のBitmap
例に示すように、同じインターフェイスをShape
実装できます。 さらに、1 つのオブジェクトで複数のインターフェイスを実装できます。 たとえば、グラフィックス ライブラリでは、グラフィックス オブジェクトの保存と読み込みをサポートする名前 ISerializable
のインターフェイスを定義できます。 次に、次のクラス宣言を検討します。
// An interface for serialization.
class ISerializable
{
public:
virtual void Load(PCWSTR filename) = 0; // Load from file.
virtual void Save(PCWSTR filename) = 0; // Save to file.
};
// Declarations of drawable object types.
class Shape : public IDrawable
{
...
};
class Bitmap : public IDrawable, public ISerializable
{
...
};
この例では、クラスISerializable
は Bitmap
. プログラムでは、このメソッドを使用してビットマップを保存または読み込むことができます。 ただし、クラスは Shape
実装 ISerializable
されないため、その機能は公開されません。 次の図は、この例の継承関係を示しています。
このセクションでは、インターフェイスの概念的な基礎を調べましたが、これまでは実際の COM コードを見ていません。 まず、COM アプリケーションで行う必要がある最初の操作として、COM ライブラリを初期化します。