Was ist eine COM-Schnittstelle?

Wenn Sie C# oder Java kennen, sollten Schnittstellen ein vertrautes Konzept sein. Eine Schnittstelle definiert eine Reihe von Methoden, die ein Objekt unterstützen kann, ohne etwas über die Implementierung zu diktieren. Die -Schnittstelle markiert eine klare Grenze zwischen Code, der eine -Methode aufruft, und dem Code, der die -Methode implementiert. In der Informatik ist der Aufrufer von der Implementierung entkoppelt .

Abbildung der Schnittstellengrenze zwischen einem Objekt und einer Anwendung

In C++ ist die nächste Entsprechung zu einer Schnittstelle eine reine virtuelle Klasse, d. h. eine Klasse, die nur reine virtuelle Methoden und keine anderen Member enthält. Hier sehen Sie ein hypothetisches Beispiel für eine Schnittstelle:

// The following is not actual COM.

// Pseudo-C++:

interface IDrawable
{
    void Draw();
};

Die Idee dieses Beispiels ist, dass ein Satz von -Objekten in einer Grafikbibliothek gezeichnet werden kann. Die IDrawable -Schnittstelle definiert die Vorgänge, die jedes zeichnungsfähige Objekt unterstützen muss. (Gemäß der Konvention beginnen Schnittstellennamen mit "I".) In diesem Beispiel definiert die IDrawable -Schnittstelle einen einzelnen Vorgang: Draw.

Alle Schnittstellen sind abstrakt, sodass ein Programm keine instance eines IDrawable Objekts als solches erstellen konnte. Beispielsweise würde der folgende Code nicht kompiliert.

IDrawable draw;
draw.Draw();

Stattdessen stellt die Grafikbibliothek Objekte bereit, die die IDrawable -Schnittstelle implementieren. Beispielsweise kann die Bibliothek ein Shape-Objekt zum Zeichnen von Formen und ein Bitmapobjekt zum Zeichnen von Bildern bereitstellen. In C++ wird dies von einer allgemeinen abstrakten Basisklasse geerbt:

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

Die Shape Klassen und Bitmap definieren zwei unterschiedliche Typen von zeichnungsfähigen Objekten. Jede Klasse erbt von IDrawable und stellt eine eigene Implementierung der Draw -Methode bereit. Natürlich können sich die beiden Implementierungen erheblich unterscheiden. Beispielsweise kann die Shape::Draw -Methode eine Reihe von Linien rastern, während Bitmap::Draw ein Array von Pixeln durchblitzt wird.

Ein Programm, das diese Grafikbibliothek verwendet, würde Objekte und Bitmap durch Zeiger bearbeitenShape, anstatt oder Bitmap direkt zu verwenden ShapeIDrawable.

IDrawable *pDrawable = CreateTriangleShape();

if (pDrawable)
{
    pDrawable->Draw();
}

Hier sehen Sie ein Beispiel, das eine Schleife über ein Array von IDrawable Zeigern führt. Das Array kann eine heterogene Auswahl von Formen, Bitmaps und anderen Grafikobjekten enthalten, solange jedes Objekt im Array erbt IDrawable.

void DrawSomeShapes(IDrawable **drawableArray, size_t count)
{
    for (size_t i = 0; i < count; i++)
    {
        drawableArray[i]->Draw();
    }
}

Ein wichtiger Punkt bei COM ist, dass der aufrufende Code nie den Typ der abgeleiteten Klasse sieht. Anders ausgedrückt: Sie würden niemals eine Variable vom Typ Shape oder Bitmap in Ihrem Code deklarieren. Alle Vorgänge für Shapes und Bitmaps werden mithilfe von IDrawable Zeigern ausgeführt. Auf diese Weise behält COM eine strikte Trennung zwischen Schnittstelle und Implementierung bei. Die Implementierungsdetails der Shape Klassen und Bitmap können sich ändern, z. B. um Fehler zu beheben oder neue Funktionen hinzuzufügen, ohne änderungen am aufrufenden Code.

In einer C++-Implementierung werden Schnittstellen mithilfe einer Klasse oder Struktur deklariert.

Hinweis

Die Codebeispiele in diesem Thema sollen allgemeine Konzepte und keine praxisnahe Praxis vermitteln. Das Definieren neuer COM-Schnittstellen geht über den Rahmen dieser Reihe hinaus, aber Sie würden eine Schnittstelle nicht direkt in einer Headerdatei definieren. Stattdessen wird eine COM-Schnittstelle mithilfe einer Sprache namens Interface Definition Language (IDL) definiert. Die IDL-Datei wird von einem IDL-Compiler verarbeitet, der eine C++-Headerdatei generiert.

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

Wenn Sie mit COM arbeiten, ist es wichtig zu beachten, dass Schnittstellen keine Objekte sind. Dabei handelt es sich um Auflistungen von Methoden, die Objekte implementieren müssen. Mehrere Objekte können dieselbe Schnittstelle implementieren, wie in den Beispielen Shape und Bitmap gezeigt. Darüber hinaus kann ein Objekt mehrere Schnittstellen implementieren. Beispielsweise kann die Grafikbibliothek eine Schnittstelle namens ISerializable definieren, die das Speichern und Laden von Grafikobjekten unterstützt. Betrachten Sie nun die folgenden Klassendeklarationen:

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

In diesem Beispiel implementiert ISerializabledie Bitmap -Klasse . Das Programm könnte diese Methode verwenden, um die Bitmap zu speichern oder zu laden. Die Shape -Klasse implementiert ISerializablejedoch nicht , sodass diese Funktionalität nicht verfügbar gemacht wird. Das folgende Diagramm zeigt die Vererbungsbeziehungen in diesem Beispiel.

Abbildung der Schnittstellenvererbung, wobei die Shape- und Bitmapklassen auf idrawable zeigen, aber nur bitmaps, die auf iserializable zeigen

In diesem Abschnitt wurden die konzeptionellen Grundlagen von Schnittstellen untersucht, aber bisher haben wir keinen tatsächlichen COM-Code gesehen. Wir beginnen mit dem ersten, was jede COM-Anwendung tun muss: Initialisieren der COM-Bibliothek.

Nächste

Initialisieren der COM-Bibliothek