Classe CComObjectRootEx
Questa classe fornisce metodi per gestire la gestione del conteggio dei riferimenti agli oggetti sia per gli oggetti non aggregati che per gli oggetti aggregati.
Sintassi
template<class ThreadModel>
class CComObjectRootEx : public CComObjectRootBase
Parametri
ThreadModel
Classe i cui metodi implementano il modello di threading desiderato. È possibile scegliere in modo esplicito il modello di threading impostando ThreadModel su CComSingleThreadModel, CComMultiThreadModel o CComMultiThreadModelNoCS. È possibile accettare il modello di thread predefinito del server impostando ThreadModel su CComObjectThreadModel o CComGlobalsThreadModel.
Membri
Metodi
Funzione | Descrizione |
---|---|
CComObjectRootEx | Costruttore. |
InternalAddRef | Incrementa il conteggio dei riferimenti per un oggetto non raggruppato. |
InternalRelease | Decrementa il conteggio dei riferimenti per un oggetto non raggruppato. |
Blocca | Se il modello di thread è multithreading, ottiene la proprietà di un oggetto sezione critica. |
Aprire | Se il modello di thread è multithreading, rilascia la proprietà di un oggetto sezione critico. |
Metodi CComObjectRootBase
Funzione | Descrizione |
---|---|
FinalConstruct | Eseguire l'override nella classe per eseguire qualsiasi inizializzazione richiesta dall'oggetto. |
FinalRelease | Eseguire l'override nella classe per eseguire qualsiasi pulizia richiesta dall'oggetto. |
OuterAddRef | Incrementa il conteggio dei riferimenti per un oggetto aggregato. |
OuterQueryInterface | Delega all'esterno IUnknown di un oggetto aggregato. |
OuterRelease | Decrementa il conteggio dei riferimenti per un oggetto aggregato. |
Funzioni statiche
Funzione | Descrizione |
---|---|
InternalQueryInterface | Delega all'oggetto IUnknown di un oggetto nonaggregato. |
ObjectMain | Chiamato durante l'inizializzazione e la terminazione del modulo per le classi derivate elencate nella mappa oggetti. |
Membri dei dati
Membro dati | Descrizione |
---|---|
m_dwRef | Con m_pOuterUnknown , parte di un'unione. Utilizzato quando l'oggetto non viene aggregato per contenere il conteggio dei riferimenti di AddRef e Release . |
m_pOuterUnknown | Con m_dwRef , parte di un'unione. Utilizzato quando l'oggetto viene aggregato per contenere un puntatore all'oggetto sconosciuto esterno. |
Osservazioni:
CComObjectRootEx
gestisce la gestione del conteggio dei riferimenti agli oggetti sia per gli oggetti non aggregati che per gli oggetti aggregati. Contiene il conteggio dei riferimenti all'oggetto se l'oggetto non viene aggregato e mantiene il puntatore all'oggetto sconosciuto esterno se l'oggetto viene aggregato. Per gli oggetti aggregati, CComObjectRootEx
i metodi possono essere utilizzati per gestire l'errore dell'oggetto interno da costruire e per proteggere l'oggetto esterno dall'eliminazione quando vengono rilasciate interfacce interne o l'oggetto interno viene eliminato.
Una classe che implementa un server COM deve ereditare da CComObjectRootEx
o CComObjectRoot.
Se la definizione della classe specifica la macro DECLARE_POLY_AGGREGATABLE , ATL crea un'istanza di CComPolyObject<CYourClass>
quando IClassFactory::CreateInstance
viene chiamato . Durante la creazione, viene controllato il valore dell'elemento sconosciuto esterno. Se è NULL, IUnknown
viene implementato per un oggetto nonaggregato. Se l'elemento sconosciuto esterno non è NULL, IUnknown
viene implementato per un oggetto aggregato.
Se la classe non specifica la macro DECLARE_POLY_AGGREGATABLE, ATL crea un'istanza di CAggComObject<CYourClass>
per gli oggetti aggregati o un'istanza di CComObject<CYourClass>
per gli oggetti non aggregati.
Il vantaggio dell'uso CComPolyObject
consiste nell'evitare di avere sia CComAggObject
che CComObject
nel modulo per gestire i casi aggregati e non aggregati. Un singolo CComPolyObject
oggetto gestisce entrambi i casi. Pertanto, nel modulo è presente una sola copia della tabella virtuale e una copia delle funzioni. Se la tabella virtuale è grande, questa operazione può ridurre notevolmente le dimensioni del modulo. Tuttavia, se la tabella virtuale è piccola, l'uso CComPolyObject
di può comportare dimensioni del modulo leggermente maggiori perché non è ottimizzato per un oggetto aggregato o nonaggregato, come sono CComAggObject
e CComObject
.
Se l'oggetto è aggregato, IUnknown viene implementato da CComAggObject
o CComPolyObject
. Queste classi delegano QueryInterface
, AddRef
e Release
chiamano a CComObjectRootEx
's OuterQueryInterface
, OuterAddRef
e OuterRelease
per inoltrare all'oggetto sconosciuto esterno. In genere, si esegue l'override CComObjectRootEx::FinalConstruct
nella classe per creare qualsiasi oggetto aggregato ed eseguire l'override per liberare CComObjectRootEx::FinalRelease
tutti gli oggetti aggregati.
Se l'oggetto non è aggregato, IUnknown
viene implementato da CComObject
o CComPolyObject
. In questo caso, le chiamate a QueryInterface
, AddRef
e Release
vengono delegate a CComObjectRootEx
's InternalQueryInterface
, InternalAddRef
e InternalRelease
per eseguire le operazioni effettive.
Requisiti
Intestazione: atlcom.h
CComObjectRootEx::CComObjectRootEx
Il costruttore inizializza il conteggio dei riferimenti a 0.
CComObjectRootEx();
CComObjectRootEx::FinalConstruct
È possibile eseguire l'override di questo metodo nella classe derivata per eseguire qualsiasi inizializzazione necessaria per l'oggetto.
HRESULT FinalConstruct();
Valore restituito
Restituisce S_OK in caso di esito positivo o di uno dei valori HRESULT dell'errore standard.
Osservazioni:
Per impostazione predefinita, restituisce CComObjectRootEx::FinalConstruct
semplicemente S_OK.
L'inizializzazione invece FinalConstruct
del costruttore della classe offre vantaggi:
Non è possibile restituire un codice di stato da un costruttore, ma è possibile restituire un valore HRESULT tramite il
FinalConstruct
valore restituito di . Quando gli oggetti della classe vengono creati usando la class factory standard fornita da ATL, questo valore restituito viene propagato al client COM che consente di fornire informazioni dettagliate sugli errori.Non è possibile chiamare funzioni virtuali tramite il meccanismo di funzione virtuale dal costruttore di una classe. La chiamata di una funzione virtuale dal costruttore di una classe comporta una chiamata risolta in modo statico alla funzione così come viene definita in quel punto nella gerarchia di ereditarietà. Le chiamate a funzioni virtuali pure generano errori del linker.
La classe non è la classe più derivata nella gerarchia di ereditarietà. Si basa su una classe derivata fornita da ATL per fornire alcune delle relative funzionalità. Esiste una buona probabilità che l'inizializzazione debba usare le funzionalità fornite da tale classe (questo è certamente vero quando gli oggetti della classe devono aggregare altri oggetti), ma il costruttore nella classe non ha modo di accedere a tali funzionalità. Il codice di costruzione per la classe viene eseguito prima che la classe più derivata sia completamente costruita.
Tuttavia,
FinalConstruct
viene chiamato immediatamente dopo che la classe più derivata è completamente costruita consentendo di chiamare le funzioni virtuali e di usare l'implementazione del conteggio dei riferimenti fornita da ATL.
Esempio
In genere, eseguire l'override di questo metodo nella classe derivata da CComObjectRootEx
per creare qualsiasi oggetto aggregato. Ad esempio:
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.
Se la costruzione non riesce, è possibile restituire un errore. È anche possibile utilizzare la macro DECLARE_PROTECT_FINAL_CONSTRUCT per proteggere l'oggetto esterno dall'eliminazione se, durante la creazione, l'oggetto aggregato interno incrementa il conteggio dei riferimenti a 0.
Ecco un modo tipico per creare un'aggregazione:
Aggiungere un
IUnknown
puntatore all'oggetto classe e inizializzarlo in NULL nel costruttore.Eseguire l'override per creare l'aggregazione
FinalConstruct
.Usare il
IUnknown
puntatore definito come parametro per la macro COM_INTERFACE_ENTRY_AGGREGATE .Eseguire l'override per rilasciare il
IUnknown
puntatoreFinalRelease
.
CComObjectRootEx::FinalRelease
È possibile eseguire l'override di questo metodo nella classe derivata per eseguire qualsiasi pulizia necessaria per l'oggetto.
void FinalRelease();
Osservazioni:
Per impostazione predefinita, CComObjectRootEx::FinalRelease
non esegue alcuna operazione.
L'esecuzione della pulizia in FinalRelease
è preferibile aggiungere codice al distruttore della classe poiché l'oggetto è ancora completamente costruito nel punto in cui FinalRelease
viene chiamato . In questo modo è possibile accedere in modo sicuro ai metodi forniti dalla classe più derivata. Ciò è particolarmente importante per liberare qualsiasi oggetto aggregato prima dell'eliminazione.
CComObjectRootEx::InternalAddRef
Incrementa il numero di riferimenti di un oggetto nonaggregato di 1.
ULONG InternalAddRef();
Valore restituito
Valore che può essere utile per la diagnostica e il test.
Osservazioni:
Se il modello di thread è multithreading, InterlockedIncrement
viene usato per impedire a più thread di modificare contemporaneamente il conteggio dei riferimenti.
CComObjectRootEx::InternalQueryInterface
Recupera un puntatore all'interfaccia richiesta.
static HRESULT InternalQueryInterface(
void* pThis,
const _ATL_INTMAP_ENTRY* pEntries,
REFIID iid,
void** ppvObject);
Parametri
pThis
[in] Puntatore all'oggetto contenente la mappa COM di interfacce esposte a QueryInterface
.
pEntries
[in] Puntatore alla struttura che accede a _ATL_INTMAP_ENTRY
una mappa delle interfacce disponibili.
iid
[in] GUID dell'interfaccia richiesta.
ppvObject
[out] Puntatore al puntatore dell'interfaccia specificato in iid o NULL se l'interfaccia non viene trovata.
Valore restituito
Uno dei valori HRESULT standard.
Osservazioni:
InternalQueryInterface
gestisce solo le interfacce nella tabella di mappe COM. Se l'oggetto è aggregato, InternalQueryInterface
non delega all'oggetto sconosciuto esterno. È possibile immettere le interfacce nella tabella mappa COM con la macro COM_INTERFACE_ENTRY o una delle relative varianti.
CComObjectRootEx::InternalRelease
Decrementa il conteggio dei riferimenti di un oggetto non raggruppato di 1.
ULONG InternalRelease();
Valore restituito
In entrambe le compilazioni non di debug e debug, questa funzione restituisce un valore che può essere utile per la diagnostica o il test. Il valore esatto restituito dipende da molti fattori, ad esempio il sistema operativo usato e può, o meno, essere il conteggio dei riferimenti.
Osservazioni:
Se il modello di thread è multithreading, InterlockedDecrement
viene usato per impedire a più thread di modificare contemporaneamente il conteggio dei riferimenti.
CComObjectRootEx::Lock
Se il modello di thread è multithreading, questo metodo chiama la funzione API Win32 EnterCriticalSection, che attende fino a quando il thread non può assumere la proprietà dell'oggetto sezione critico ottenuto tramite un membro dati privato.
void Lock();
Osservazioni:
Al termine dell'esecuzione del codice protetto, il thread deve chiamare Unlock
per rilasciare la proprietà della sezione critica.
Se il modello di thread è a thread singolo, questo metodo non esegue alcuna operazione.
CComObjectRootEx::m_dwRef
Parte di un'unione che accede a quattro byte di memoria.
long m_dwRef;
Osservazioni:
Con m_pOuterUnknown
, parte di un'unione:
union {
long m_dwRef;
IUnknown* m_pOuterUnknown;
};
Se l'oggetto non è aggregato, il conteggio dei riferimenti a cui si accede e Release
viene archiviato AddRef
in m_dwRef
. Se l'oggetto viene aggregato, il puntatore all'elemento sconosciuto esterno viene archiviato in m_pOuterUnknown.
CComObjectRootEx::m_pOuterUnknown
Parte di un'unione che accede a quattro byte di memoria.
IUnknown*
m_pOuterUnknown;
Osservazioni:
Con m_dwRef
, parte di un'unione:
union {
long m_dwRef;
IUnknown* m_pOuterUnknown;
};
Se l'oggetto viene aggregato, il puntatore all'oggetto sconosciuto esterno viene archiviato in m_pOuterUnknown
. Se l'oggetto non è aggregato, il conteggio dei riferimenti a cui si accede e Release
viene archiviato AddRef
in m_dwRef.
CComObjectRootEx::ObjectMain
Per ogni classe elencata nella mappa oggetti, questa funzione viene chiamata una volta quando il modulo viene inizializzato e di nuovo quando viene terminato.
static void WINAPI ObjectMain(bool bStarting);
Parametri
bStarting
[out] Il valore è TRUE se la classe viene inizializzata; in caso contrario FALSE.
Osservazioni:
Il valore del parametro bStarting indica se il modulo viene inizializzato o terminato. L'implementazione predefinita di non esegue alcuna operazione, ma è possibile eseguire l'override di ObjectMain
questa funzione nella classe per inizializzare o pulire le risorse da allocare per la classe . Si noti che viene chiamato prima che ObjectMain
vengano richieste istanze della classe .
ObjectMain
viene chiamato dal punto di ingresso della DLL, quindi il tipo di operazione che la funzione del punto di ingresso può eseguire è limitata. Per altre informazioni su queste restrizioni, vedere DLL e comportamento della libreria di runtime di Visual C++ e DllMain.
Esempio
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
Incrementa il conteggio dei riferimenti dell'elemento sconosciuto esterno di un'aggregazione.
ULONG OuterAddRef();
Valore restituito
Valore che può essere utile per la diagnostica e il test.
CComObjectRootEx::OuterQueryInterface
Recupera un puntatore indiretto all'interfaccia richiesta.
HRESULT OuterQueryInterface(REFIID iid, void** ppvObject);
Parametri
iid
[in] GUID dell'interfaccia richiesta.
ppvObject
[out] Puntatore al puntatore all'interfaccia specificato in iid o NULL se l'aggregazione non supporta l'interfaccia.
Valore restituito
Uno dei valori HRESULT standard.
CComObjectRootEx::OuterRelease
Decrementa il conteggio dei riferimenti dell'elemento sconosciuto esterno di un'aggregazione.
ULONG OuterRelease();
Valore restituito
Nelle compilazioni non di debug restituisce sempre 0. Nelle compilazioni di debug restituisce un valore che può essere utile per la diagnostica o il test.
CComObjectRootEx::Unlock
Se il modello di thread è multithreading, questo metodo chiama la funzione API Win32 LeaveCriticalSection, che rilascia la proprietà dell'oggetto sezione critica ottenuto tramite un membro dati privato.
void Unlock();
Osservazioni:
Per ottenere la proprietà, il thread deve chiamare Lock
. Ogni chiamata a Lock
richiede una chiamata corrispondente a Unlock
per rilasciare la proprietà della sezione critica.
Se il modello di thread è a thread singolo, questo metodo non esegue alcuna operazione.
Vedi anche
Classe CComAggObject
Classe CComObject
Classe CComPolyObject
Cenni preliminari sulla classe