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 OuterAddRef
OuterQueryInterface
CComObjectRootEx
, , 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
, AddRef
i Release
są delegowane do CComObjectRootEx
parametrów InternalQueryInterface
s , InternalAddRef
i 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