Udostępnij za pośrednictwem


Klasa CComObjectRootEx

Ta klasa udostępnia metody obsługi zarządzania liczbą odwołań do obiektów zarówno dla obiektów nieagregowanych, jak i zagregowanych.

Składnia

template<class ThreadModel>
class CComObjectRootEx : public CComObjectRootBase

Parametry

ThreadModel
Klasa, której metody implementują żądany model wątków. Możesz jawnie wybrać model wątków, ustawiając element ThreadModel na CComSingleThreadModel, CComMultiThreadModel lub CComMultiThreadModelNoCS. Domyślny model wątków serwera można zaakceptować, ustawiając wartość ThreadModel na CComObjectThreadModel lub CComGlobalsThreadModel.

Elementy członkowskie

Metody

Function opis
CComObjectRootEx Konstruktor.
InternalAddRef Zwiększa liczbę odwołań dla nieagregowanego obiektu.
Wydanie wewnętrzne Dekrementuje liczbę odwołań dla nieagregowanego obiektu.
Zablokuj Jeśli model wątku jest wielowątkowy, uzyskuje własność obiektu sekcji krytycznej.
Odblokować Jeśli model wątku jest wielowątkowy, zwalnia własność obiektu sekcji krytycznej.

Metody CComObjectRootBase

Function opis
FinalConstruct Zastąpij w klasie, aby wykonać dowolną inicjację wymaganą przez obiekt.
Wersja ostateczna Zastąpij w klasie, aby wykonać wszelkie operacje oczyszczania wymagane przez obiekt.
OuterAddRef Zwiększa liczbę odwołań dla zagregowanego obiektu.
OuterQueryInterface Delegaty na zewnątrz IUnknown zagregowanego obiektu.
Wydanie zewnętrzne Dekrementuje liczbę odwołań dla zagregowanego obiektu.

Funkcje statyczne

Function opis
InternalQueryInterface Delegaty do IUnknown obiektu nieagregowanego.
ObjectMain Wywoływana podczas inicjowania i kończenia modułu dla klas pochodnych wymienionych na mapie obiektów.

Składowe danych

Element członkowski danych opis
m_dwRef Z m_pOuterUnknown, częścią unii. Używany, gdy obiekt nie jest agregowany do przechowywania liczby odwołań i AddRef Release.
m_pOuterUnknown Z m_dwRef, częścią unii. Używany, gdy obiekt jest agregowany do przechowywania wskaźnika do zewnętrznej nieznanej.

Uwagi

CComObjectRootEx obsługuje zarządzanie liczbą odwołań do obiektów zarówno nieagregowanych, jak i zagregowanych. Przechowuje liczbę odwołań do obiektu, jeśli obiekt nie jest agregowany i przechowuje wskaźnik do zewnętrznej nieznanej, jeśli obiekt jest agregowany. W przypadku zagregowanych obiektów CComObjectRootEx metody mogą służyć do obsługi awarii obiektu wewnętrznego do konstruowania i ochrony obiektu zewnętrznego przed usunięciem, gdy interfejsy wewnętrzne są zwalniane lub obiekt wewnętrzny jest usuwany.

Klasa, która implementuje serwer COM, musi dziedziczyć z CComObjectRootEx lub CComObjectRoot.

Jeśli definicja klasy określa makro DECLARE_POLY_AGGREGATABLE , ATL tworzy wystąpienie, CComPolyObject<CYourClass> gdy IClassFactory::CreateInstance jest wywoływany. Podczas tworzenia sprawdzana jest wartość zewnętrznej nieznanej. Jeśli ma wartość NULL, IUnknown jest implementowany dla obiektu nieagregowanego. Jeśli zewnętrzna nieznana wartość nie ma wartości NULL, IUnknown jest implementowana dla zagregowanego obiektu.

Jeśli klasa nie określa makra DECLARE_POLY_AGGREGATABLE, usługa ATL tworzy wystąpienie CAggComObject<CYourClass> dla zagregowanych obiektów lub wystąpienie CComObject<CYourClass> obiektów nieagregowanych.

Zaletą użycia CComPolyObject jest unikanie CComAggObject obsługi zagregowanych i nieagregowanych przypadków zarówno w module, jak i CComObject w module. Pojedynczy CComPolyObject obiekt obsługuje oba przypadki. W związku z tym w module istnieje tylko jedna kopia tabeli wirtualnej i jedna kopia funkcji. Jeśli twoja tabela wirtualna jest duża, może to znacznie zmniejszyć rozmiar modułu. Jeśli jednak tabela wirtualna jest mała, użycie CComPolyObject metody może spowodować nieco większy rozmiar modułu, ponieważ nie jest zoptymalizowany pod kątem zagregowanego lub nieagregowanego obiektu, podobnie jak i CComAggObject CComObject.

Jeśli obiekt jest agregowany, element IUnknown jest implementowany przez element CComAggObject lub CComPolyObject. Te klasy delegować QueryInterface, AddRef, i Release wywołania do OuterAddRefOuterQueryInterfaceCComObjectRootEx, , i OuterRelease do przekazywania do zewnętrznej nieznanej. Zazwyczaj przesłonięć CComObjectRootEx::FinalConstruct w klasie, aby utworzyć wszystkie zagregowane obiekty i zastąpić CComObjectRootEx::FinalRelease wszystkie zagregowane obiekty.

Jeśli obiekt nie jest agregowany, IUnknown jest implementowany przez CComObject program lub CComPolyObject. W takim przypadku wywołania metody QueryInterface, AddRefi Release są delegowane do CComObjectRootExparametrów InternalQueryInterfaces , InternalAddRefi InternalRelease do wykonywania rzeczywistych operacji.

Wymagania

Nagłówek: atlcom.h

CComObjectRootEx::CComObjectRootEx

Konstruktor inicjuje liczbę odwołań do 0.

CComObjectRootEx();

CComObjectRootEx::FinalConstruct

Tę metodę można zastąpić w klasie pochodnej, aby wykonać dowolną inicjację wymaganą dla obiektu.

HRESULT FinalConstruct();

Wartość zwracana

Zwraca S_OK powodzenia lub jednej ze standardowych wartości HRESULT błędu.

Uwagi

Domyślnie CComObjectRootEx::FinalConstruct po prostu zwraca S_OK.

Istnieją zalety przeprowadzania inicjalizacji FinalConstruct zamiast konstruktora klasy:

  • Nie można zwrócić kodu stanu z konstruktora, ale można zwrócić wartość HRESULT za pomocą wartości zwracanej FinalConstruct. Gdy obiekty klasy są tworzone przy użyciu standardowej fabryki klas dostarczonej przez ATL, ta wartość zwracana jest propagowana z powrotem do klienta COM, co pozwala na podanie im szczegółowych informacji o błędzie.

  • Nie można wywoływać funkcji wirtualnych za pośrednictwem mechanizmu funkcji wirtualnej z konstruktora klasy. Wywołanie funkcji wirtualnej z konstruktora klasy powoduje statycznie rozpoznane wywołanie funkcji, ponieważ jest ono zdefiniowane w tym momencie w hierarchii dziedziczenia. Wywołania czystych funkcji wirtualnych powodują błędy konsolidatora.

    Klasa nie jest najbardziej pochodną klasą w hierarchii dziedziczenia — opiera się na klasie pochodnej dostarczonej przez ATL w celu zapewnienia niektórych jej funkcji. Istnieje duża szansa, że inicjowanie będzie musiało korzystać z funkcji dostarczonych przez tę klasę (z pewnością jest to prawdą, gdy obiekty klasy muszą agregować inne obiekty), ale konstruktor w klasie nie ma możliwości uzyskania dostępu do tych funkcji. Kod konstrukcyjny klasy jest wykonywany przed w pełni skonstruowaną najbardziej pochodną klasą.

    Jednak jest wywoływany natychmiast po tym, FinalConstruct jak najbardziej pochodna klasa jest w pełni skonstruowana, co umożliwia wywoływanie funkcji wirtualnych i używanie implementacji zliczania odwołań dostarczonej przez ATL.

Przykład

Zazwyczaj zastąp tę metodę w klasie pochodnej CComObjectRootEx w celu utworzenia wszystkich zagregowanych obiektów. Na przykład:

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.

Jeśli konstrukcja zakończy się niepowodzeniem, możesz zwrócić błąd. Można również użyć DECLARE_PROTECT_FINAL_CONSTRUCT makra, aby chronić obiekt zewnętrzny przed usunięciem, jeśli podczas tworzenia wewnętrzny zagregowany obiekt zwiększa liczbę odwołań, a następnie dekrementuje liczbę do 0.

Oto typowy sposób tworzenia agregacji:

  • IUnknown Dodaj wskaźnik do obiektu klasy i zainicjuj go do wartości NULL w konstruktorze.

  • Zastąpić FinalConstruct , aby utworzyć agregację.

  • Użyj wskaźnika zdefiniowanego IUnknown jako parametru do makra COM_INTERFACE_ENTRY_AGGREGATE .

  • Zastąpij FinalRelease IUnknown , aby zwolnić wskaźnik.

CComObjectRootEx::FinalRelease

Tę metodę można zastąpić w klasie pochodnej, aby wykonać dowolne czyszczenie wymagane dla obiektu.

void FinalRelease();

Uwagi

Domyślnie CComObjectRootEx::FinalRelease nic nie robi.

Oczyszczanie w in FinalRelease jest preferowane, aby dodać kod do destruktora klasy, ponieważ obiekt jest nadal w pełni skonstruowany w punkcie, w którym FinalRelease jest wywoływany. Dzięki temu można bezpiecznie uzyskać dostęp do metod udostępnianych przez najbardziej pochodną klasę. Jest to szczególnie ważne w przypadku zwalniania wszystkich zagregowanych obiektów przed usunięciem.

CComObjectRootEx::InternalAddRef

Zwiększa liczbę odwołań obiektu nieagregowanego o 1.

ULONG InternalAddRef();

Wartość zwracana

Wartość, która może być przydatna do diagnostyki i testowania.

Uwagi

Jeśli model wątku jest wielowątkowy, InterlockedIncrement służy do zapobiegania zmianie liczby odwołań w tym samym czasie przez więcej niż jeden wątek.

CComObjectRootEx::InternalQueryInterface

Pobiera wskaźnik do żądanego interfejsu.

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

Parametry

pThis
[in] Wskaźnik do obiektu, który zawiera mapę COM interfejsów uwidocznionych na QueryInterface.

PEntries
[in] Wskaźnik do struktury, która uzyskuje dostęp do _ATL_INTMAP_ENTRY mapy dostępnych interfejsów.

identyfikator iid
[in] Identyfikator GUID żądanego interfejsu.

ppvObject
[out] Wskaźnik do wskaźnika interfejsu określony w identyfikatorze iid lub null, jeśli interfejs nie zostanie znaleziony.

Wartość zwracana

Jedna ze standardowych wartości HRESULT.

Uwagi

InternalQueryInterface obsługuje tylko interfejsy w tabeli mapy COM. Jeśli obiekt jest agregowany, InternalQueryInterface nie deleguje do zewnętrznej nieznanej. Interfejsy można wprowadzać do tabeli mapy COM przy użyciu makra COM_INTERFACE_ENTRY lub jednego z jego wariantów.

CComObjectRootEx::InternalRelease

Dekrementuje liczbę odwołań obiektu nieagregowanego o 1.

ULONG InternalRelease();

Wartość zwracana

W kompilacjach bez debugowania i debugowania ta funkcja zwraca wartość, która może być przydatna do diagnostyki lub testowania. Dokładna zwracana wartość zależy od wielu czynników, takich jak używany system operacyjny, i może, lub nie, być może, jest liczbą odwołań.

Uwagi

Jeśli model wątku jest wielowątkowy, InterlockedDecrement służy do zapobiegania zmianie liczby odwołań w tym samym czasie przez więcej niż jeden wątek.

CComObjectRootEx::Lock

Jeśli model wątku jest wielowątkowy, ta metoda wywołuje funkcję interfejsu API Win32 EnterCriticalSection, która czeka, aż wątek może przejąć własność obiektu sekcji krytycznej uzyskanej za pośrednictwem prywatnego elementu członkowskiego danych.

void Lock();

Uwagi

Po zakończeniu wykonywania chronionego kodu wątek musi wywołać Unlock metodę zwolnienia własności sekcji krytycznej.

Jeśli model wątku jest jednowątkowy, ta metoda nic nie robi.

CComObjectRootEx::m_dwRef

Część unii, która uzyskuje dostęp do czterech bajtów pamięci.

long m_dwRef;

Uwagi

Z m_pOuterUnknown, częścią unii:

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Jeśli obiekt nie jest agregowany, liczba odwołań, do których AddRef uzyskuje dostęp i Release jest przechowywana w pliku m_dwRef. Jeśli obiekt jest agregowany, wskaźnik do zewnętrznej nieznanej jest przechowywany w m_pOuterUnknown.

CComObjectRootEx::m_pOuterUnknown

Część unii, która uzyskuje dostęp do czterech bajtów pamięci.

IUnknown*
    m_pOuterUnknown;

Uwagi

Z m_dwRef, częścią unii:

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Jeśli obiekt jest zagregowany, wskaźnik do zewnętrznej nieznanej jest przechowywany w pliku m_pOuterUnknown. Jeśli obiekt nie jest agregowany, liczba odwołań, do których AddRef uzyskuje dostęp i Release jest przechowywana w m_dwRef.

CComObjectRootEx::ObjectMain

Dla każdej klasy wymienionej na mapie obiektów ta funkcja jest wywoływana raz po zainicjowaniu modułu i ponownie po zakończeniu.

static void WINAPI ObjectMain(bool bStarting);

Parametry

bStarting
[out] Wartość ma wartość TRUE, jeśli klasa jest inicjowana; w przeciwnym razie FAŁSZ.

Uwagi

Wartość parametru bStarting wskazuje, czy moduł jest inicjowany, czy zakończony. Domyślna implementacja ObjectMain nic nie robi, ale można zastąpić tę funkcję w klasie, aby zainicjować lub wyczyścić zasoby, które chcesz przydzielić dla klasy. Należy pamiętać, że ObjectMain jest wywoływana przed żądaniem wszystkich wystąpień klasy.

ObjectMain jest wywoływana z punktu wejścia biblioteki DLL, więc typ operacji, którą może wykonać funkcja punktu wejścia, jest ograniczona. Aby uzyskać więcej informacji na temat tych ograniczeń, zobacz Biblioteki DLL i zachowanie biblioteki uruchomieniowej Visual C++ i DllMain.

Przykład

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

Zwiększa liczbę odwołań zewnętrznego nieznanego agregacji.

ULONG OuterAddRef();

Wartość zwracana

Wartość, która może być przydatna do diagnostyki i testowania.

CComObjectRootEx::OuterQueryInterface

Pobiera wskaźnik pośredni do żądanego interfejsu.

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

Parametry

identyfikator iid
[in] Identyfikator GUID żądanego interfejsu.

ppvObject
[out] Wskaźnik do wskaźnika interfejsu określony w identyfikatorze iid lub NULL, jeśli agregacja nie obsługuje interfejsu.

Wartość zwracana

Jedna ze standardowych wartości HRESULT.

CComObjectRootEx::OuterRelease

Dekrementuje liczbę odwołań zewnętrznego nieznanego agregacji.

ULONG OuterRelease();

Wartość zwracana

W kompilacjach innych niż debugowanie zawsze zwraca wartość 0. W kompilacjach debugowania zwraca wartość, która może być przydatna do diagnostyki lub testowania.

CComObjectRootEx::Unlock

Jeśli model wątku jest wielowątkowy, ta metoda wywołuje funkcję interfejsu API Win32 LeaveCriticalSection, która zwalnia własność obiektu sekcji krytycznej uzyskanego za pośrednictwem prywatnego elementu członkowskiego danych.

void Unlock();

Uwagi

Aby uzyskać własność, wątek musi wywołać metodę Lock. Każde wywołanie Lock wymaga odpowiedniego wywołania do Unlock wydania własności sekcji krytycznej.

Jeśli model wątku jest jednowątkowy, ta metoda nic nie robi.

Zobacz też

Klasa CComAggObject
Klasa CComObject
Klasa CComPolyObject
Omówienie klasy