Was ist eine COM-Schnittstelle?
Wenn Sie C# oder Java kennen, sollten Schnittstellen ein vertrautes Konzept sein. Eine Schnittstelle definiert einen Satz 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 Computer science ist der Aufrufer von der Implementierung entkoppelt.

In C++ ist das nächste Äquivalent zu einer Schnittstelle eine reine virtuelle Klasse, d. B. eine Klasse, die nur rein virtuelle Methoden und keine anderen Member enthält. Hier ist 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 zeichnen werden kann. Die IDrawable -Schnittstelle definiert die Vorgänge, die jedes drawable-Objekt unterstützen muss. (Standardmäßig beginnen Schnittstellennamen mit "I".) In diesem Beispiel definiert die IDrawable -Schnittstelle einen einzelnen Vorgang: Draw .
Alle Schnittstellen sind abstrakt, sodass ein Programm keine Instanz eines Objekts IDrawable als solche erstellen konnte. Der folgende Code würde z. B. nicht kompiliert werden.
IDrawable draw;
draw.Draw();
Stattdessen stellt die Grafikbibliothek Objekte bereit, die die -Schnittstelle IDrawable implementieren. Beispielsweise könnte die Bibliothek ein Formobjekt zum Zeichnen von Formen und ein Bitmapobjekt zum Zeichnen von Bildern bereitstellen. In C++ erfolgt dies durch Erben von einer allgemeinen abstrakten Basisklasse:
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 definieren zwei Bitmap unterschiedliche Typen von drawable-Objekten. Jede Klasse erbt von IDrawable und bietet ihre eigene Implementierung der Draw -Methode. Natürlich können sich die beiden Implementierungen erheblich unterscheiden. Die -Methode kann z. B. eine Reihe von Zeilen rastern, während ein Array von Shape::Draw Bitmap::Draw Pixeln blitt.
Ein Programm, das diese Grafikbibliothek verwendet, würde - und -Objekte über Zeiger bearbeiten, anstatt Shape Bitmap - oder IDrawable Shape Bitmap -Zeiger direkt zu verwenden.
IDrawable *pDrawable = CreateTriangleShape();
if (pDrawable)
{
pDrawable->Draw();
}
Hier ist ein Beispiel, das eine Schleife über ein Array von IDrawable Zeigern durchfingt. Das Array kann ein heterogenes Spektrum von Formen, Bitmaps und anderen Grafikobjekten enthalten, solange jedes Objekt im Array IDrawable erbt.
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 erkennt. Anders ausgedrückt: Sie würden nie eine Variable vom Typ oder Shape Bitmap in Ihrem Code deklarieren. Alle Vorgänge für Formen und Bitmaps werden mit IDrawable Zeigern ausgeführt. Auf diese Weise behält COM eine strikte Trennung zwischen Schnittstelle und Implementierung bei. Die Implementierungsdetails der Klassen und können sich ohne Änderungen am aufrufenden Code ändern, z. B. um Fehler zu beheben oder neue Shape Bitmap Funktionen hinzuzufügen.
In einer C++-Implementierung werden Schnittstellen mithilfe einer Klasse oder Struktur deklariert.
Hinweis
Die Codebeispiele in diesem Thema sollen allgemeine Konzepte vermitteln, nicht die praxisorientierte Praxis. 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. Es handelt sich um Auflistungen von Methoden, die Objekte implementieren müssen. Mehrere Objekte können die gleiche 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 definieren, ISerializable 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 Bitmap die -Klasse ISerializable . Das Programm könnte diese Methode verwenden, um die Bitmap zu speichern oder zu laden. Die -Klasse Shape implementiert jedoch nicht , sodass sie diese Funktionalität nicht verfügbar ISerializable macht. Das folgende Diagramm zeigt die Vererbungsbeziehungen in diesem Beispiel.

In diesem Abschnitt wurde die konzeptionelle Basis von Schnittstellen untersucht, aber bisher haben wir keinen tatsächlichen COM-Code gesehen. Wir beginnen mit dem ersten Schritt, den jede COM-Anwendung tun muss: Initialisieren der COM-Bibliothek.