Condividi tramite


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, AddRefe Release chiamano a CComObjectRootEx's OuterQueryInterface, OuterAddRefe 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, AddRefe Release vengono delegate a CComObjectRootEx's InternalQueryInterface, InternalAddRefe 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 FinalConstructvalore 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