Sdílet prostřednictvím


CComObjectRootEx – třída

Tato třída poskytuje metody pro zpracování správy počtu odkazů na objekty pro neagregované i agregované objekty.

Syntaxe

template<class ThreadModel>
class CComObjectRootEx : public CComObjectRootBase

Parametry

ThreadModel
Třída, jejíž metody implementují požadovaný model vláken. Model vláken můžete explicitně zvolit nastavením ThreadModel na CComSingleThreadModel, CComMultiThreadModel nebo CComMultiThreadModelNoCS. Výchozí model vlákna serveru můžete přijmout nastavením ThreadModel na CComObjectThreadModel nebo CComGlobalsThreadModel.

Členové

Metody

Function Popis
CComObjectRootEx Konstruktor
InternalAddRef Zvýší počet odkazů pro neagregovaný objekt.
InternalRelease Sníží počet odkazů pro neagregovaný objekt.
Uzamknout Pokud je model vlákna vícevláknový, získá vlastnictví kritického objektu oddílu.
Odemknout Pokud je model vlákna vícevláknový, uvolní vlastnictví kritického objektu oddílu.

CComObjectRootBase – metody

Function Popis
FinalConstruct Přepište ve třídě, aby se provedla jakákoli inicializace vyžadovaná objektem.
FinalRelease Přepište ve třídě, aby se provedlo vyčištění požadované objektem.
OuterAddRef Zvýší počet odkazů pro agregovaný objekt.
OuterQueryInterface Deleguje na vnější část IUnknown agregovaného objektu.
Vnější verze Sníží počet odkazů pro agregovaný objekt.

Statické funkce

Function Popis
InternalQueryInterface Deleguje na IUnknown neagregovaný objekt.
ObjectMain Volá se během inicializace a ukončení modulu pro odvozené třídy uvedené v mapě objektu.

Datové členy

Datový člen Popis
m_dwRef S m_pOuterUnknown, součástí sjednocení. Používá se, pokud objekt není agregován k uložení referenčního AddRef počtu a Release.
m_pOuterUnknown S m_dwRef, součástí sjednocení. Používá se při agregaci objektu pro uložení ukazatele na vnější neznámý objekt.

Poznámky

CComObjectRootEx zpracovává správu počtu odkazů na objekty pro neagregované i agregované objekty. Obsahuje počet odkazů na objekt, pokud objekt není agregován, a uchovává ukazatel na vnější neznámý objekt, pokud je objekt agregován. U agregovaných objektů CComObjectRootEx lze metody použít ke zpracování selhání vnitřního objektu k vytvoření a k ochraně vnějšího objektu před odstraněním při uvolnění vnitřních rozhraní nebo odstranění vnitřního objektu.

Třída, která implementuje server COM musí dědit z CComObjectRootEx nebo CComObjectRoot.

Pokud definice třídy určuje DECLARE_POLY_AGGREGATABLE makro, ATL vytvoří instanci CComPolyObject<CYourClass> , kdy IClassFactory::CreateInstance je volána. Při vytváření se zkontroluje hodnota vnější neznámé hodnoty. Pokud má hodnotu NULL, IUnknown implementuje se pro neagregovaný objekt. Pokud vnější neznámý není NULL, IUnknown je implementováno pro agregovaný objekt.

Pokud vaše třída neurčí DECLARE_POLY_AGGREGATABLE makro, ATL vytvoří instanci CAggComObject<CYourClass> pro agregované objekty nebo instanci CComObject<CYourClass> pro neagregované objekty.

Výhodou použití CComPolyObject je, že se v modulu nemusíte zabývat CComAggObjectCComObject agregovanými a neagregovanými případy. Jeden CComPolyObject objekt zpracovává oba případy. Proto v modulu existuje pouze jedna kopie virtuální tabulky a jedna kopie funkcí. Pokud je vaše virtuální tabulka velká, může se tím podstatně zmenšit velikost modulu. Pokud je však tabulka vtable malá, může použití CComPolyObject vést k mírně větší velikosti modulu, protože není optimalizovaná pro agregovaný nebo neagregovaný objekt, jak jsou CComAggObject a CComObject.

Pokud je objekt agregovaný, je IUnknown implementován pomocí CComAggObject nebo CComPolyObject. Tyto třídy delegují QueryInterface, AddRefa Release volání CComObjectRootEx' s OuterQueryInterface, OuterAddRefa OuterRelease předat do vnější neznámé. Obvykle přepíšete CComObjectRootEx::FinalConstruct ve své třídě, aby se vytvořily všechny agregované objekty, a přepsání CComObjectRootEx::FinalRelease uvolnit všechny agregované objekty.

Pokud objekt není agregovaný, IUnknown implementuje ho CComObject nebo CComPolyObject. V tomto případě jsou volání , QueryInterfaceAddRefa Release jsou delegovány na CComObjectRootEx' s InternalQueryInterface, InternalAddRefa InternalRelease provádět skutečné operace.

Požadavky

Hlavička: atlcom.h

CComObjectRootEx::CComObjectRootEx

Konstruktor inicializuje počet odkazů na 0.

CComObjectRootEx();

CComObjectRootEx::FinalConstruct

Tuto metodu můžete v odvozené třídě přepsat, aby se provedla jakákoli inicializace požadovaná pro objekt.

HRESULT FinalConstruct();

Vrácená hodnota

Vrátí S_OK při úspěchu nebo jedné ze standardních hodnot HRESULT chyby.

Poznámky

Ve výchozím nastavení CComObjectRootEx::FinalConstruct jednoduše vrátí S_OK.

Provádění inicializace je FinalConstruct výhodné místo konstruktoru třídy:

  • Stavový kód nelze vrátit z konstruktoru, ale hodnotu HRESULT můžete vrátit pomocí návratové FinalConstructhodnoty. Když se objekty vaší třídy vytvářejí pomocí standardní továrny třídy poskytované ATL, tato návratová hodnota se rozšíří zpět do klienta COM, což vám umožní poskytnout je s podrobnými informacemi o chybách.

  • Virtuální funkce nelze volat prostřednictvím mechanismu virtuální funkce z konstruktoru třídy. Volání virtuální funkce z konstruktoru třídy má za následek staticky vyřešené volání funkce, protože je definováno v tomto okamžiku v hierarchii dědičnosti. Volání čistě virtuálních funkcí způsobí chyby linkeru.

    Vaše třída není nejvíce odvozenou třídou v hierarchii dědičnosti – spoléhá na odvozenou třídu, kterou atL poskytuje, aby poskytovala některé její funkce. Existuje dobrá šance, že vaše inicializace bude muset používat funkce poskytované touto třídou (to je jistě pravda, pokud objekty vaší třídy potřebují agregovat jiné objekty), ale konstruktor ve vaší třídě nemá žádný způsob, jak k těmto funkcím přistupovat. Kód konstrukce pro vaši třídu se provede před tím, než se úplně zkonstruuje odvozená třída.

    Je FinalConstruct však volána okamžitě po nejvíce odvozené třídě je plně sestavena, takže můžete volat virtuální funkce a použít implementaci počítání odkazů poskytovanou ATL.

Příklad

Obvykle přepsat tuto metodu ve třídě odvozené z CComObjectRootEx vytvořit všechny agregované objekty. Příklad:

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.

Pokud konstrukce selže, můžete vrátit chybu. Pomocí DECLARE_PROTECT_FINAL_CONSTRUCT makra můžete také chránit vnější objekt před odstraněním, pokud během vytváření interní agregovaný objekt zvýší počet odkazů a potom sníží počet na 0.

Tady je typický způsob vytvoření agregace:

  • IUnknown Přidejte ukazatel na objekt třídy a inicializujete ho na hodnotu NULL v konstruktoru.

  • Přepsání FinalConstruct pro vytvoření agregace

  • IUnknown Použijte ukazatel, který jste definovali jako parametr na makro COM_INTERFACE_ENTRY_AGGREGATE.

  • Přepsáním uvolněte FinalReleaseIUnknown ukazatel.

CComObjectRootEx::FinalRelease

Tuto metodu v odvozené třídě můžete přepsat, aby se provedlo vyčištění požadované pro objekt.

void FinalRelease();

Poznámky

Ve výchozím nastavení CComObjectRootEx::FinalRelease nic nedělá.

Provádění čištění FinalRelease je vhodnější přidat kód do destruktoru třídy, protože objekt je stále plně vytvořen v okamžiku, kdy FinalRelease je volána. To vám umožní bezpečně přistupovat k metodám poskytovaným nejvíce odvozenou třídou. To je zvlášť důležité pro uvolnění všech agregovaných objektů před odstraněním.

CComObjectRootEx::InternalAddRef

Zvýší počet odkazů neagregovaného objektu o 1.

ULONG InternalAddRef();

Vrácená hodnota

Hodnota, která může být užitečná pro diagnostiku a testování.

Poznámky

Pokud je model vlákna vícevláknový, InterlockedIncrement slouží k zabránění změně počtu odkazů ve stejnou dobu více než jedno vlákno.

CComObjectRootEx::InternalQueryInterface

Načte ukazatel na požadované rozhraní.

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

Parametry

PThis
[v] Ukazatel na objekt, který obsahuje mapu modelu COM rozhraní vystavených QueryInterface.

PEntries
[v] Ukazatel na _ATL_INTMAP_ENTRY strukturu, která přistupuje k mapě dostupných rozhraní.

Iid
[v] Identifikátor GUID požadovaného rozhraní.

ppvObject
[ven] Ukazatel na ukazatel rozhraní zadaný v iid nebo NULL, pokud rozhraní není nalezeno.

Vrácená hodnota

Jedna ze standardních hodnot HRESULT.

Poznámky

InternalQueryInterface zpracovává pouze rozhraní v tabulce mapování modelu COM. Pokud je objekt agregovaný, InternalQueryInterface neleguje na vnější neznámý objekt. Rozhraní můžete zadat do tabulky mapování modelu COM s makrem COM_INTERFACE_ENTRY nebo některou z jejích variant.

CComObjectRootEx::InternalRelease

Sníží počet odkazů neagregovaného objektu o 1.

ULONG InternalRelease();

Vrácená hodnota

V sestaveních, které nejsou ladicí, i ladicí, vrátí tato funkce hodnotu, která může být užitečná pro diagnostiku nebo testování. Přesná vrácená hodnota závisí na mnoha faktorech, jako je použitý operační systém, a může nebo nemusí být referenčním počtem.

Poznámky

Pokud je model vlákna vícevláknový, InterlockedDecrement slouží k zabránění změně počtu odkazů ve stejnou dobu více než jedno vlákno.

CComObjectRootEx::Lock

Pokud je model vlákna vícevláknový, tato metoda volá funkci rozhraní API Win32 EnterCriticalSection, která čeká, dokud vlákno nemůže převzít vlastnictví kritického objektu oddílu získaného prostřednictvím soukromého datového členu.

void Lock();

Poznámky

Po dokončení provádění chráněného kódu musí vlákno volat Unlock uvolnění vlastnictví kritické části.

Pokud je model vlákna jednovláknový, tato metoda nedělá nic.

CComObjectRootEx::m_dwRef

Část sjednocení, která přistupuje ke čtyřbajtům paměti.

long m_dwRef;

Poznámky

S m_pOuterUnknownčástí sjednocení:

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Pokud objekt není agregován, počet odkazů, ke které AddRef přistupuje a Release je uložen v m_dwRef. Pokud je objekt agregován, je ukazatel na vnější neznámý uložen v m_pOuterUnknown.

CComObjectRootEx::m_pOuterUnknown

Část sjednocení, která přistupuje ke čtyřbajtům paměti.

IUnknown*
    m_pOuterUnknown;

Poznámky

S m_dwRefčástí sjednocení:

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Je-li objekt agregován, je ukazatel na vnější neznámý uložen v m_pOuterUnknown. Pokud objekt není agregovaný, počet odkazů, ke které AddRef se přistupuje, a Release je uložen v m_dwRef.

CComObjectRootEx::ObjectMain

Pro každou třídu uvedenou v mapě objektu se tato funkce volá jednou při inicializaci modulu a znovu po ukončení.

static void WINAPI ObjectMain(bool bStarting);

Parametry

bStarting
[ven] Hodnota je TRUE, pokud je třída inicializována; jinak NEPRAVDA.

Poznámky

Hodnota parametru bStarting označuje, jestli se modul inicializuje nebo ukončuje. Výchozí implementace ObjectMain nic nedělá, ale můžete tuto funkci ve třídě přepsat tak, aby inicializovala nebo vyčistila prostředky, které chcete přidělit pro třídu. Všimněte si, že ObjectMain je volána před vyžádáním instancí třídy.

ObjectMain je volána ze vstupního bodu knihovny DLL, takže typ operace, kterou může funkce vstupního bodu provést, je omezena. Další informace o těchtoomezeních

Příklad

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

Zvýší počet odkazů vnějšího neznámého agregace.

ULONG OuterAddRef();

Vrácená hodnota

Hodnota, která může být užitečná pro diagnostiku a testování.

CComObjectRootEx::OuterQueryInterface

Načte nepřímý ukazatel na požadované rozhraní.

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

Parametry

Iid
[v] Identifikátor GUID požadovaného rozhraní.

ppvObject
[ven] Ukazatel na ukazatel rozhraní zadaný v iid nebo NULL, pokud agregace nepodporuje rozhraní.

Vrácená hodnota

Jedna ze standardních hodnot HRESULT.

CComObjectRootEx::OuterRelease

Sníží počet odkazů vnějšího neznámého agregace.

ULONG OuterRelease();

Vrácená hodnota

V neladit sestavení vždy vrátí hodnotu 0. V buildech ladění vrátí hodnotu, která může být užitečná pro diagnostiku nebo testování.

CComObjectRootEx::Unlock

Pokud je model vlákna vícevláknový, tato metoda volá funkci rozhraní API Win32 LeaveCriticalSection, která uvolní vlastnictví kritického objektu oddílu získaného prostřednictvím soukromého datového členu.

void Unlock();

Poznámky

Chcete-li získat vlastnictví, vlákno musí volat Lock. Každé volání Lock vyžaduje odpovídající volání k Unlock uvolnění vlastnictví kritického oddílu.

Pokud je model vlákna jednovláknový, tato metoda nedělá nic.

Viz také

CComAggObject – třída
CComObject – třída
CComPolyObject – třída
Přehled třídy