什麼是 COM 介面?

如果您知道 C# 或 JAVA,介面應該是熟悉的概念。 介面會定義一組物件可以支援的方法,而不需要聽寫實作的任何內容。 介面會標示呼叫 方法的程式碼與實作 方法的程式碼之間的清楚界限。 在電腦科學方面,呼叫端會與實作 分離

此圖顯示物件與應用程式之間的介面界限

在 C++ 中,與介面最接近的對等專案是純虛擬類別,也就是只包含純虛擬方法且不含其他成員的類別。 以下是介面的假設範例:

// The following is not actual COM.

// Pseudo-C++:

interface IDrawable
{
    void Draw();
};

此範例的概念是,某些圖形庫中的一組物件是可繪製的。 介面 IDrawable 會定義任何可繪製物件必須支援的作業。 (依慣例,介面名稱開頭為 「I」.) 在此範例中 IDrawable ,介面會定義單一作業: 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.
};

ShapeBitmap 類別會定義兩種不同的可繪製物件類型。 每個類別都會繼承自 IDrawable ,並提供它自己的 方法實作 Draw 。 當然,這兩個實作可能會有很大的差異。 例如, Shape::Draw 方法可能會點陣化一組線條,而 Bitmap::Draw 會閃爍圖元陣列。

使用此圖形庫的程式會透過 IDrawable 指標操作 ShapeBitmap 物件,而不是直接使用 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 會維持介面與實作之間的嚴格分隔。 和 Bitmap 類別的實作 Shape 詳細資料可能會變更,例如修正 Bug 或新增新功能,而不需要變更呼叫程式碼。

在 C++ 實作中,介面是使用類別或結構來宣告。

注意

本主題中的程式碼範例旨在傳達一般概念,而非真實世界的做法。 定義新的 COM 介面超出此系列的範圍,但您不會直接在標頭檔中定義介面。 相反地,COM 介面會使用稱為介面定義語言的語言 (IDL) 來定義。 IDL 檔案是由 IDL 編譯器處理,其會產生 C++ 標頭檔。

class IDrawable
{
public:
    virtual void Draw() = 0;
};

當您使用 COM 時,請務必記住介面不是物件。 它們是物件必須實作的方法集合。 數個物件可以實作相同的介面,如 和 Bitmap 範例所示 Shape 。 此外,一個物件可以實作數個介面。 例如,圖形庫可能會定義名為 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
{
    ...
};

在此範例中,類別會 Bitmap 實作 ISerializable 。 程式可以使用這個方法來儲存或載入點陣圖。 不過,類別不會實 ISerializableShape ,因此不會公開該功能。 下圖顯示此範例中的繼承關聯性。

顯示介面繼承的圖例,其中圖形和點陣圖類別指向可 idrawable,但只有指向 iserializable 的點陣圖

本節已檢查介面的概念基礎,但到目前為止,我們看不到實際的 COM 程式碼。 我們將從任何 COM 應用程式必須執行的第一件事開始:初始化 COM 程式庫。

下一個

初始化 COM 程式庫