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
, AddRef
und Release
rufen ' CComObjectRootEx
s OuterQueryInterface
, OuterAddRef
und 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
, AddRef
und Release
sie werden an CComObjectRootEx
's InternalQueryInterface
, InternalAddRef
und 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
FinalConstruct
Rü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 denIUnknown
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_dwRef
dieser 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