COM インターフェイスとは

C# または Java がわかっている場合、インターフェイスは使い慣れた概念である必要があります。 インターフェイスは、実装について何もディクテーションすることなく、オブジェクトがサポートできる一連のメソッドを定義 します 。 インターフェイスは、メソッドを呼び出すコードとメソッドを実装するコードの間の明確な境界をマークします。 コンピューター サイエンスの用語では、呼び出し元は実装から 切り離されます

illustration showing the interface boundary between an object and an application

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.
};

クラスとクラスBitmapShape、2 種類の描画可能なオブジェクトを定義します。 各クラスは、メソッドを IDrawable 継承し、独自の実装を Draw 提供します。 当然、2 つの実装は大きく異なる場合があります。 たとえば、このメソッドは Shape::Draw 一連の線をラスター化し Bitmap::Draw 、ピクセルの配列を blit する場合があります。

このグラフィックス ライブラリを使用するプログラムは、直接またはポインターを使用するのではなく、ポインターを使用してIDrawableShapeオブジェクトをBitmap操作ShapeBitmapします。

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 はインターフェイスと実装の間で厳密な分離を維持します。 およびクラスの実装のShapeBitmap詳細は、バグの修正や新機能の追加など、呼び出し元のコードに変更を加えずに変更される可能性があります。

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
{
    ...
};

この例では、クラスISerializableBitmap . プログラムでは、このメソッドを使用してビットマップを保存または読み込むことができます。 ただし、クラスは Shape 実装 ISerializableされないため、その機能は公開されません。 次の図は、この例の継承関係を示しています。

illustration showing interface inheritance, with the shape and bitmap classes pointing to idrawable, but only bitmap pointing to iserializable

このセクションでは、インターフェイスの概念的な基礎を調べましたが、これまでは実際の COM コードを見ていません。 まず、COM アプリケーションで行う必要がある最初の操作として、COM ライブラリを初期化します。

次へ

COM ライブラリの初期化