Freigeben über


CComObjectRootEx-Klasse

Diese Klasse stellt Methoden zum Behandeln der Objektverweisanzahlverwaltung für nicht aggregierte und aggregierte Objekte bereit.

Syntax

template<class ThreadModel>
class CComObjectRootEx : public CComObjectRootBase

Parameter

ThreadModel
Die Klasse, deren Methoden das gewünschte Threadingmodell implementieren. Sie können das Threadingmodell explizit auswählen, indem Sie ThreadModel auf CComSingleThreadModel, CComMultiThreadModel oder CComMultiThreadModelNoCS festlegen. Sie können das Standardthreadmodell des Servers akzeptieren, indem Sie ThreadModel auf CComObjectThreadModel oder CComGlobalsThreadModel festlegen.

Member

Methoden

Funktion Beschreibung
CComObjectRootEx Konstruktor.
InternalAddRef Erhöht die Referenzanzahl für ein nicht aggregiertes Objekt.
InternalRelease Erhöht die Referenzanzahl für ein nicht aggregiertes Objekt.
Sperren Wenn das Threadmodell multithreaded ist, erhält der Besitz eines kritischen Abschnittsobjekts.
Entsperren Wenn das Threadmodell multithreaded ist, wird der Besitz eines kritischen Abschnittsobjekts freigegeben.

CComObjectRootBase-Methoden

Funktion Beschreibung
FinalConstruct Überschreiben Sie die Klasse, um alle vom Objekt benötigten Initialisierungen auszuführen.
FinalRelease Überschreiben Sie die Klasse, um alle vom Objekt benötigten Bereinigungen durchzuführen.
OuterAddRef Erhöht die Referenzanzahl für ein aggregiertes Objekt.
OuterQueryInterface Stellvertretungen an das Äußere IUnknown eines aggregierten Objekts.
OuterRelease Erhöht die Referenzanzahl für ein aggregiertes Objekt.

Statische Funktionen

Funktion Beschreibung
InternalQueryInterface Delegiert an das IUnknown nicht aggregierte Objekt.
ObjectMain Wird während der Modulinitialisierung und Beendigung für abgeleitete Klassen aufgerufen, die in der Objektzuordnung aufgeführt sind.

Datenelemente

Datenmememm Beschreibung
m_dwRef Mit m_pOuterUnknown, Teil einer Gewerkschaft. Wird verwendet, wenn das Objekt nicht aggregiert wird, um die Referenzanzahl von AddRef und .Release
m_pOuterUnknown Mit m_dwRef, Teil einer Gewerkschaft. Wird verwendet, wenn das Objekt aggregiert wird, um einen Zeiger auf das äußere Unbekannte zu halten.

Hinweise

CComObjectRootEx behandelt die Verwaltung der Objektverweisanzahl sowohl für nicht aggregierte als auch für aggregierte Objekte. Es enthält die Objektverweisanzahl, wenn Ihr Objekt nicht aggregiert wird, und hält den Mauszeiger auf das äußere Unbekannte, wenn das Objekt aggregiert wird. Bei aggregierten Objekten können Methoden verwendet werden, CComObjectRootEx um den Fehler des inneren Objekts zu konstruieren und das äußere Objekt vor dem Löschen zu schützen, wenn innere Schnittstellen freigegeben werden oder das innere Objekt gelöscht wird.

Eine Klasse, die einen COM-Server implementiert, muss von CComObjectRootEx oder CComObjectRoot erben.

Wenn die Klassendefinition das DECLARE_POLY_AGGREGATABLE Makro angibt, erstellt ATL eine Instanz des Aufrufs IClassFactory::CreateInstance CComPolyObject<CYourClass>. Während der Erstellung wird der Wert des äußeren Unbekannten überprüft. Wenn es NULL ist, IUnknown wird für ein nicht aggregiertes Objekt implementiert. Wenn das äußere Unbekannte nicht NULL ist, IUnknown wird für ein aggregiertes Objekt implementiert.

Wenn ihre Klasse das DECLARE_POLY_AGGREGATABLE Makro nicht angibt, erstellt ATL eine Instanz für CAggComObject<CYourClass> aggregierte Objekte oder eine Instanz von CComObject<CYourClass> nicht aggregierten Objekten.

Der Vorteil der Verwendung CComPolyObject besteht darin, dass Sie sowohl als auch CComAggObject CComObject in Ihrem Modul vermeiden, die aggregierten und nicht aggregierten Fälle zu verarbeiten. Ein einzelnes CComPolyObject Objekt behandelt beide Fälle. Daher sind nur eine Kopie der vtable und eine Kopie der Funktionen in Ihrem Modul vorhanden. Wenn die vtable groß ist, kann dies die Modulgröße erheblich verringern. Wenn die vtable jedoch klein ist, kann die Verwendung CComPolyObject zu einer etwas größeren Modulgröße führen, da sie nicht für ein aggregiertes oder nicht aggregiertes Objekt optimiert ist, wie es sind CComAggObject und CComObject.

Wenn Ihr Objekt aggregiert wird, wird IUnknown von CComAggObject oder CComPolyObject. Diese Klassen delegieren QueryInterface, AddRefund Release rufen ' CComObjectRootExs OuterQueryInterface, OuterAddRefund OuterRelease um an das äußere Unbekannte weiterzuleiten. In der Regel überschreiben CComObjectRootEx::FinalConstruct Sie die Klasse, um aggregierte Objekte zu erstellen und CComObjectRootEx::FinalRelease alle aggregierten Objekte freizulegen.

Wenn Ihr Objekt nicht aggregiert wird, IUnknown wird von CComObject oder CComPolyObject. In diesem Fall werden Aufrufe von QueryInterface, AddRefund Release sie werden an CComObjectRootEx's InternalQueryInterface, InternalAddRefund InternalRelease zum Ausführen der tatsächlichen Vorgänge delegiert.

Anforderungen

Kopfzeile: atlcom.h

CComObjectRootEx::CComObjectRootEx

Der Konstruktor initialisiert die Referenzanzahl auf 0.

CComObjectRootEx();

CComObjectRootEx::FinalConstruct

Sie können diese Methode in ihrer abgeleiteten Klasse überschreiben, um alle initialisierungen durchzuführen, die für Ihr Objekt erforderlich sind.

HRESULT FinalConstruct();

Rückgabewert

Gibt S_OK bei Erfolg oder einem der Standardfehler-HRESULT-Werte zurück.

Hinweise

Standardmäßig CComObjectRootEx::FinalConstruct wird einfach S_OK zurückgegeben.

Es gibt Vorteile beim Ausführen der Initialisierung FinalConstruct anstelle des Konstruktors Ihrer Klasse:

  • Sie können keinen Statuscode aus einem Konstruktor zurückgeben, aber Sie können ein HRESULT mithilfe des FinalConstructRückgabewerts zurückgeben. Wenn Objekte Ihrer Klasse mithilfe der standardklassenfactory erstellt werden, die von ATL bereitgestellt wird, wird dieser Rückgabewert an den COM-Client weitergegeben, sodass Sie diese mit detaillierten Fehlerinformationen bereitstellen können.

  • Sie können virtuelle Funktionen nicht über den Mechanismus der virtuellen Funktion aus dem Konstruktor einer Klasse aufrufen. Das Aufrufen einer virtuellen Funktion aus dem Konstruktor einer Klasse führt zu einem statisch aufgelösten Aufruf der Funktion, wie sie an diesem Punkt in der Vererbungshierarchie definiert ist. Aufrufe von reinen virtuellen Funktionen führen zu Verknüpfungsfehlern.

    Ihre Klasse ist nicht die abgeleitete Klasse in der Vererbungshierarchie – sie basiert auf einer abgeleiteten Klasse, die von ATL bereitgestellt wird, um einige ihrer Funktionen bereitzustellen. Es gibt eine gute Chance, dass Ihre Initialisierung die von dieser Klasse bereitgestellten Features verwenden muss (dies gilt sicherlich, wenn Objekte Ihrer Klasse andere Objekte aggregieren müssen), aber der Konstruktor in Ihrer Klasse hat keine Möglichkeit, auf diese Features zuzugreifen. Der Konstruktionscode für Ihre Klasse wird ausgeführt, bevor die abgeleitete Klasse vollständig erstellt wird.

    Wird jedoch unmittelbar aufgerufen, FinalConstruct nachdem die am häufigsten abgeleitete Klasse vollständig erstellt wurde, sodass Sie virtuelle Funktionen aufrufen und die von ATL bereitgestellte Referenzzählungsimplementierung verwenden können.

Beispiel

Überschreiben Sie diese Methode in der Klasse, die von CComObjectRootEx der abgeleiteten Klasse abgeleitet wird, um aggregierte Objekte zu erstellen. Zum Beispiel:

class ATL_NO_VTABLE CMyAggObject :
   public CComObjectRootEx<CComSingleThreadModel>,
   public CComCoClass<CMyAggObject, &CLSID_MyAggObject>,
   public IDispatchImpl<IMyAggObject, &IID_IMyAggObject, &LIBID_NVC_ATL_COMLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
   DECLARE_GET_CONTROLLING_UNKNOWN()
   HRESULT FinalConstruct()
   {
      return CoCreateInstance(CLSID_MyCustomClass, GetControllingUnknown(), 
         CLSCTX_ALL, IID_IUnknown, (void**)&m_pMyCustomClass);
   }

   IMyCustomClass* m_pMyCustomClass;

   // Remainder of class declaration omitted.

Wenn die Konstruktion fehlschlägt, können Sie einen Fehler zurückgeben. Sie können auch das Makro DECLARE_PROTECT_FINAL_CONSTRUCT verwenden, um das äußere Objekt vor dem Löschen zu schützen, wenn das interne aggregierte Objekt die Referenzanzahl erhöht und dann die Anzahl auf 0 erhöht.

Hier ist eine typische Methode zum Erstellen eines Aggregats:

  • Fügen Sie ihrem Klassenobjekt einen IUnknown Zeiger hinzu, und initialisieren Sie ihn im Konstruktor auf NULL.

  • Überschreiben FinalConstruct , um das Aggregat zu erstellen.

  • Verwenden Sie den IUnknown Zeiger, den Sie als Parameter für das COM_INTERFACE_ENTRY_AGGREGATE Makro definiert haben.

  • Überschreiben FinalRelease , um den IUnknown Zeiger freizugeben.

CComObjectRootEx::FinalRelease

Sie können diese Methode in Ihrer abgeleiteten Klasse überschreiben, um alle für Ihr Objekt erforderlichen Bereinigungen durchzuführen.

void FinalRelease();

Hinweise

Führt standardmäßig CComObjectRootEx::FinalRelease nichts aus.

Das Ausführen der Bereinigung FinalRelease ist vorzuziehen, um code zum Destruktor Der Klasse hinzuzufügen, da das Objekt an dem Punkt, an FinalRelease dem aufgerufen wird, noch vollständig konstruiert ist. Auf diese Weise können Sie sicher auf die methoden zugreifen, die von der am häufigsten abgeleiteten Klasse bereitgestellt werden. Dies ist besonders wichtig zum Freigeben aller aggregierten Objekte vor dem Löschen.

CComObjectRootEx::InternalAddRef

Erhöht die Verweisanzahl eines nicht aggregierten Objekts um 1.

ULONG InternalAddRef();

Rückgabewert

Ein Wert, der für Diagnose und Tests nützlich sein kann.

Hinweise

Wenn das Threadmodell multithreaded ist, wird verwendet, um zu verhindern, InterlockedIncrement dass mehrere Threads gleichzeitig die Referenzanzahl ändern.

CComObjectRootEx::InternalQueryInterface

Ruft einen Zeiger auf die angeforderte Schnittstelle ab.

static HRESULT InternalQueryInterface(
    void* pThis,
    const _ATL_INTMAP_ENTRY* pEntries,
    REFIID iid,
    void** ppvObject);

Parameter

pThis
[in] Ein Zeiger auf das Objekt, das die COM-Zuordnung von Schnittstellen enthält, die verfügbar gemacht werden QueryInterface.

pEntries
[in] Ein Zeiger auf die Struktur, die _ATL_INTMAP_ENTRY auf eine Karte der verfügbaren Schnittstellen zugreift.

iid
[in] Die GUID der angeforderten Schnittstelle.

ppvObject
[out] Ein Zeiger auf den in iid angegebenen Schnittstellenzeiger oder NULL, wenn die Schnittstelle nicht gefunden wird.

Rückgabewert

Einer der HRESULT-Standardwerte.

Hinweise

InternalQueryInterface behandelt nur Schnittstellen in der COM-Zuordnungstabelle. Wenn Das Objekt aggregiert ist, InternalQueryInterface wird es nicht an das äußere Unbekannte delegiert. Sie können Schnittstellen in die COM-Zuordnungstabelle mit dem Makro COM_INTERFACE_ENTRY oder einer seiner Varianten eingeben.

CComObjectRootEx::InternalRelease

Erhöht die Referenzanzahl eines nicht aggregierten Objekts um 1.

ULONG InternalRelease();

Rückgabewert

In Nicht-Debug- und Debugbuilds gibt diese Funktion einen Wert zurück, der für Diagnosen oder Tests nützlich sein kann. Der genaue zurückgegebene Wert hängt von vielen Faktoren ab, z. B. dem verwendeten Betriebssystem und kann oder nicht die Referenzanzahl sein.

Hinweise

Wenn das Threadmodell multithreaded ist, wird verwendet, um zu verhindern, InterlockedDecrement dass mehrere Threads gleichzeitig die Referenzanzahl ändern.

CComObjectRootEx::Lock

Wenn das Threadmodell multithreaded ist, ruft diese Methode die Win32-API-Funktion EnterCriticalSection auf, die wartet, bis der Thread den Besitz des kritischen Abschnittsobjekts übernehmen kann, das über ein privates Datenmitglied abgerufen wurde.

void Lock();

Hinweise

Wenn die Ausführung des geschützten Codes abgeschlossen ist, muss der Thread aufrufen Unlock , um den Besitz des kritischen Abschnitts freizugeben.

Wenn das Threadmodell singlethreaded ist, führt diese Methode nichts aus.

CComObjectRootEx::m_dwRef

Teil einer Union, die auf vier Bytes Arbeitsspeicher zugreift.

long m_dwRef;

Hinweise

Mit m_pOuterUnknown, Teil einer Gewerkschaft:

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Wenn das Objekt nicht aggregiert wird, wird auf die Referenzanzahl zugegriffen AddRef und Release in m_dwRefdieser gespeichert. Wenn das Objekt aggregiert wird, wird der Zeiger auf das äußere Unbekannte in m_pOuterUnknown gespeichert.

CComObjectRootEx::m_pOuterUnknown

Teil einer Union, die auf vier Bytes Arbeitsspeicher zugreift.

IUnknown*
    m_pOuterUnknown;

Hinweise

Mit m_dwRef, Teil einer Gewerkschaft:

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Wenn das Objekt aggregiert wird, wird der Zeiger auf das äußere Unbekannte gespeichert.m_pOuterUnknown Wenn das Objekt nicht aggregiert wird, wird auf die Referenzanzahl zugegriffen AddRef und Release in m_dwRef gespeichert.

CComObjectRootEx::ObjectMain

Für jede Klasse, die in der Objektzuordnung aufgeführt ist, wird diese Funktion einmal aufgerufen, wenn das Modul initialisiert wird, und erneut, wenn sie beendet wird.

static void WINAPI ObjectMain(bool bStarting);

Parameter

bStarting
[out] Der Wert ist TRUE, wenn die Klasse initialisiert wird. andernfalls FALSE.

Hinweise

Der Wert des bStarting-Parameters gibt an, ob das Modul initialisiert oder beendet wird. Die Standardimplementierung von ObjectMain "Führt nichts aus", aber Sie können diese Funktion in Ihrer Klasse außer Kraft setzen, um Ressourcen zu initialisieren oder zu bereinigen, die Sie für die Klasse zuordnen möchten. Beachten Sie, dass ObjectMain aufgerufen wird, bevor Instanzen der Klasse angefordert werden.

ObjectMain wird vom Einstiegspunkt der DLL aufgerufen, sodass der Typ des Vorgangs, den die Einstiegspunktfunktion ausführen kann, eingeschränkt ist. Weitere Informationen zu diesen Einschränkungen finden Sie unter DLLs und Visual C++-Laufzeitbibliotheksverhalten und DllMain.

Beispiel

class ATL_NO_VTABLE CMyApp :
   public CComObjectRootEx<CComSingleThreadModel>,
   public CComCoClass<CMyApp, &CLSID_MyApp>,
   public IMyApp
{
public:
   CMyApp()
   {
   }

   static void WINAPI ObjectMain(bool bStarting)
   {
      if (bStarting)
         ;// Perform custom initialization routines
      else
         ;// Perform custom termination routines
   }

   // Remainder of class declaration omitted.

CComObjectRootEx::OuterAddRef

Erhöht die Referenzanzahl der äußeren Unbekannten einer Aggregation.

ULONG OuterAddRef();

Rückgabewert

Ein Wert, der für Diagnose und Tests nützlich sein kann.

CComObjectRootEx::OuterQueryInterface

Ruft einen indirekten Zeiger auf die angeforderte Schnittstelle ab.

HRESULT OuterQueryInterface(REFIID iid, void** ppvObject);

Parameter

iid
[in] Die GUID der angeforderten Schnittstelle.

ppvObject
[out] Ein Zeiger auf den in iid angegebenen Schnittstellenzeiger oder NULL, wenn die Aggregation die Schnittstelle nicht unterstützt.

Rückgabewert

Einer der HRESULT-Standardwerte.

CComObjectRootEx::OuterRelease

Erhöht die Bezugsanzahl der äußeren Unbekannten einer Aggregation.

ULONG OuterRelease();

Rückgabewert

Gibt in Nicht-Debug-Builds immer "0" zurück. Gibt in Debugbuilds einen Wert zurück, der für Diagnosen oder Tests nützlich sein kann.

CComObjectRootEx::Unlock

Wenn das Threadmodell multithreaded ist, ruft diese Methode die Win32-API-Funktion LeaveCriticalSection auf, die den Besitz des kritischen Abschnittsobjekts freigibt, das über ein privates Datenelement abgerufen wird.

void Unlock();

Hinweise

Zum Abrufen des Besitzes muss der Thread aufgerufen werden Lock. Jeder Aufruf erfordert einen entsprechenden Aufruf Lock , um Unlock den Besitz des kritischen Abschnitts freizugeben.

Wenn das Threadmodell singlethreaded ist, führt diese Methode nichts aus.

Siehe auch

CComAggObject-Klasse
CComObject-Klasse
CComPolyObject-Klasse
Klassenübersicht