Clase CComObjectRootEx
Esta clase proporciona métodos para controlar la administración del recuento de referencias de objetos para objetos no agregados y agregados.
Sintaxis
template<class ThreadModel>
class CComObjectRootEx : public CComObjectRootBase
Parámetros
ThreadModel
Clase cuyos métodos implementan el modelo de subprocesos deseado. Puede elegir explícitamente el modelo de subprocesos estableciendo ThreadModel en CComSingleThreadModel, CComMultiThreadModel o CComMultiThreadModelNoCS. Puede aceptar el modelo de subprocesos predeterminado del servidor estableciendo ThreadModel en CComObjectThreadModel o CComGlobalsThreadModel.
Miembros
Métodos
Función | Descripción |
---|---|
CComObjectRootEx | Constructor. |
InternalAddRef | Incrementa el recuento de referencias de un objeto no agregado. |
InternalRelease | Disminuye el recuento de referencias de un objeto no agregado. |
Bloquear | Si el modelo de subprocesos es multiproceso, obtiene la propiedad de un objeto de sección crítica. |
Unlock | Si el modelo de subprocesos es multiproceso, libera la propiedad de un objeto de sección crítica. |
Métodos de CComObjectRootBase
Función | Descripción |
---|---|
FinalConstruct | Invalide el método en la clase para realizar cualquier inicialización requerida por el objeto. |
FinalRelease | Invalide el método en la clase para realizar cualquier limpieza requerida por el objeto. |
OuterAddRef | Incrementa el recuento de referencias de un objeto agregado. |
OuterQueryInterface | Delega en el elemento IUnknown exterior de un objeto agregado. |
OuterRelease | Disminuye el recuento de referencias de un objeto agregado. |
Funciones estáticas
Función | Descripción |
---|---|
InternalQueryInterface | Delega al objeto IUnknown de un objeto no agregado. |
ObjectMain | Se le llama durante la inicialización y finalización del módulo para las clases derivadas enumeradas en el mapa de objetos. |
Miembros de datos
Miembro de datos | Descripción |
---|---|
m_dwRef | Con m_pOuterUnknown , parte de una unión. Se usa cuando el objeto no está agregado para contener el recuento de referencias de AddRef y Release . |
m_pOuterUnknown | Con m_dwRef , parte de una unión. Se usa cuando el objeto está agregado para contener un puntero al elemento desconocido externo. |
Comentarios
CComObjectRootEx
controla la administración del recuento de referencias de objetos para objetos no agregados y agregados. Contiene el recuento de referencias de objetos si el objeto no está agregado y contiene el puntero al elemento desconocido externo si el objeto está agregado. En el caso de los objetos agregados, los métodos CComObjectRootEx
se pueden usar para controlar el error del objeto interno que se va a construir y para proteger el objeto externo frente a la eliminación cuando se liberan interfaces internas o se elimina el objeto interno.
Una clase que implementa un servidor COM debe heredar de CComObjectRootEx
o CComObjectRoot.
Si la definición de clase especifica la macro DECLARE_POLY_AGGREGATABLE, ATL crea una instancia de CComPolyObject<CYourClass>
cuando se llama a IClassFactory::CreateInstance
. Durante la creación, se comprueba el valor del elemento desconocido externo. Si es null, IUnknown
se implementa para un objeto no agregado. Si el desconocido externo no es null, IUnknown
se implementa para un objeto agregado.
Si la clase no especifica la macro DECLARE_POLY_AGGREGATABLE, ATL crea una instancia de CAggComObject<CYourClass>
para objetos agregados o una instancia de CComObject<CYourClass>
para objetos no agregados.
La ventaja de usar CComPolyObject
es que evita tener tanto CComAggObject
como CComObject
en el módulo para controlar los casos agregados y no agregados. Un solo objeto CComPolyObject
controla ambos casos. Por lo tanto, solo existe una copia de la tabla virtual y una copia de las funciones en el módulo. Si la tabla virtual es grande, esto puede reducir considerablemente el tamaño del módulo. Pero si la tabla virtual es pequeña, el uso de CComPolyObject
puede dar lugar a un tamaño de módulo ligeramente mayor porque no está optimizado para un objeto agregado o no agregado, como sí lo están CComAggObject
y CComObject
.
Si el objeto está agregado, IUnknown se implementa mediante CComAggObject
o CComPolyObject
. Estas clases delegan las llamadas a QueryInterface
, AddRef
y Release
a OuterQueryInterface
, OuterAddRef
y OuterRelease
del elemento CComObjectRootEx
para su reenvío al elemento desconocido externo. Normalmente, se invalida CComObjectRootEx::FinalConstruct
en la clase para crear cualquier objeto agregado y se invalida CComObjectRootEx::FinalRelease
para liberar los objetos agregados.
Si el objeto no está agregado, IUnknown
se implementa mediante CComObject
o CComPolyObject
. En este caso, las llamadas a QueryInterface
, AddRef
y Release
se delegan en InternalQueryInterface
, InternalAddRef
y InternalRelease
de CComObjectRootEx
para llevar a cabo las operaciones reales.
Requisitos
Encabezado: atlcom.h
CComObjectRootEx::CComObjectRootEx
El constructor inicializa el recuento de referencias en 0.
CComObjectRootEx();
CComObjectRootEx::FinalConstruct
Puede invalidar este método en la clase derivada para realizar cualquier inicialización necesaria para el objeto.
HRESULT FinalConstruct();
Valor devuelto
Devuelve S_OK si se ejecuta correctamente o uno de los valores HRESULT de error estándar.
Comentarios
De manera predeterminada, CComObjectRootEx::FinalConstruct
simplemente devuelve S_OK.
Hay ventajas al realizar la inicialización en FinalConstruct
en lugar de en el constructor de la clase:
No puede devolver un código de estado desde un constructor, pero puede devolver un valor HRESULT mediante el valor devuelto de
FinalConstruct
. Cuando se crean objetos de la clase mediante el generador de clases estándar proporcionado por ATL, este valor devuelto se propaga de vuelta al cliente COM, lo que le permite proporcionarle información detallada del error.No puede llamar a funciones virtuales mediante el mecanismo de función virtual desde el constructor de una clase. Llamar a una función virtual desde el constructor de una clase da como resultado una llamada resuelta estáticamente a la función tal como se define en ese punto en la jerarquía de herencia. Las llamadas a funciones virtuales puras producen errores del enlazador.
La clase no es la clase más derivada de la jerarquía de herencia: se basa en una clase derivada proporcionada por ATL para proporcionar parte de su funcionalidad. Existe una buena posibilidad de que la inicialización tenga que usar las características proporcionadas por esa clase (esto es especialmente cierto cuando los objetos de la clase tienen que agregar otros objetos), pero el constructor de la clase no tiene forma de acceder a esas características. El código de construcción de la clase se ejecuta antes de que se construya completamente la clase más derivada.
Sin embargo, se llama a
FinalConstruct
inmediatamente después de que la clase más derivada esté totalmente construida, lo que le permite llamar a funciones virtuales y usar la implementación de recuento de referencias proporcionada por ATL.
Ejemplo
Normalmente, se invalida este método en la clase derivada de CComObjectRootEx
para crear cualquier objeto agregado. Por ejemplo:
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.
Si se produce un error en la construcción, puede devolver un error. También puede usar la macro DECLARE_PROTECT_FINAL_CONSTRUCT para proteger la eliminación del objeto externo si, durante la creación, el objeto agregado interno incrementa el recuento de referencias y, después, disminuye el recuento a 0.
Esta es una manera típica de crear un agregado:
Agregue un puntero
IUnknown
al objeto de clase e inicialícelo en NULL en el constructor.Invalide
FinalConstruct
para crear el agregado.Use el puntero
IUnknown
que definió como parámetro para la macro COM_INTERFACE_ENTRY_AGGREGATE.Invalide
FinalRelease
para liberar el punteroIUnknown
.
CComObjectRootEx::FinalRelease
Puede invalidar este método en la clase derivada para realizar cualquier limpieza necesaria para el objeto.
void FinalRelease();
Comentarios
De manera predeterminada, CComObjectRootEx::FinalRelease
no hace nada.
Es preferible realizar la limpieza en FinalRelease
para agregar código al destructor de la clase, ya que el objeto todavía está totalmente construido en el punto en el que se llama a FinalRelease
. Esto le permite acceder de forma segura a los métodos proporcionados por la clase más derivada. Esto es especialmente importante para liberar los objetos agregados antes de la eliminación.
CComObjectRootEx::InternalAddRef
Incrementa en 1 el recuento de referencias de un objeto no agregado.
ULONG InternalAddRef();
Valor devuelto
Valor que puede ser útil para los diagnósticos y las pruebas.
Comentarios
Si el modelo de subprocesos es multiproceso, se usa InterlockedIncrement
para evitar que más de un subproceso cambie el recuento de referencias al mismo tiempo.
CComObjectRootEx::InternalQueryInterface
Recupera un puntero a la interfaz solicitada.
static HRESULT InternalQueryInterface(
void* pThis,
const _ATL_INTMAP_ENTRY* pEntries,
REFIID iid,
void** ppvObject);
Parámetros
pThis
[in] Puntero al objeto que contiene el mapa COM de interfaces expuestas a QueryInterface
.
pEntries
[in] Puntero a la estructura _ATL_INTMAP_ENTRY
que accede a un mapa de interfaces disponibles.
iid
[in] GUID de la interfaz que se solicita.
ppvObject
[out] Puntero al puntero de interfaz especificado en iid o NULL si no se encuentra la interfaz.
Valor devuelto
Uno de los valores HRESULT estándar.
Comentarios
InternalQueryInterface
solo administra interfaces de la tabla de asignación COM. Si el objeto se agrega, InternalQueryInterface
no delega al desconocido externo. Para especificar interfaces en la tabla de asignación COM, puede usar la macro COM_INTERFACE_ENTRY o cualquiera de sus variantes.
CComObjectRootEx::InternalRelease
Disminuye en 1 el recuento de referencias de un objeto no agregado.
ULONG InternalRelease();
Valor devuelto
En las compilaciones de depuración y las que no son de depuración, esta función devuelve un valor que puede ser útil para diagnósticos o pruebas. El valor devuelto exacto depende de muchos factores, como el sistema operativo utilizado y, tal vez, el recuento de referencias.
Comentarios
Si el modelo de subprocesos es multiproceso, se usa InterlockedDecrement
para evitar que más de un subproceso cambie el recuento de referencias al mismo tiempo.
CComObjectRootEx::Lock
Si el modelo de subprocesos es multiproceso, este método llama a la función EnterCriticalSection de la API de Win32, que espera hasta que el subproceso pueda tomar la propiedad del objeto de sección crítica obtenido mediante un miembro de datos privado.
void Lock();
Comentarios
Cuando el código protegido termine de ejecutarse, el subproceso debe llamar a Unlock
para liberar la propiedad de la sección crítica.
Si el modelo de subprocesos es de un solo subproceso, este método no hace nada.
CComObjectRootEx::m_dwRef
Parte de una unión que tiene acceso a cuatro bytes de memoria.
long m_dwRef;
Comentarios
Con m_pOuterUnknown
, parte de una unión:
union {
long m_dwRef;
IUnknown* m_pOuterUnknown;
};
Si el objeto no está agregado, el recuento de referencias al que acceden AddRef
y Release
se almacena en m_dwRef
. Si el objeto está agregado, el puntero al elemento exterior desconocido se almacena en m_pOuterUnknown.
CComObjectRootEx::m_pOuterUnknown
Parte de una unión que tiene acceso a cuatro bytes de memoria.
IUnknown*
m_pOuterUnknown;
Comentarios
Con m_dwRef
, parte de una unión:
union {
long m_dwRef;
IUnknown* m_pOuterUnknown;
};
Si el objeto está agregado, el puntero al elemento exterior desconocido se almacena en m_pOuterUnknown
. Si el objeto no está agregado, el recuento de referencias al que acceden AddRef
y Release
se almacena en m_dwRef.
CComObjectRootEx::ObjectMain
Para cada clase enumerada en el mapa de objetos, se llama a esta función una vez cuando se inicializa el módulo y, de nuevo, cuando finaliza.
static void WINAPI ObjectMain(bool bStarting);
Parámetros
bStarting
[out] El valor es TRUE si la clase se está inicializando; en caso contrario, FALSE.
Comentarios
El valor del parámetro bStarting indica si el módulo se está inicializando o finalizando. La implementación predeterminada de ObjectMain
no hace nada, pero puede invalidar esta función en la clase para inicializar o limpiar los recursos que desea asignar para la clase. Tenga en cuenta que se llama a ObjectMain
antes de que se soliciten instancias de la clase.
Se llama a ObjectMain
desde el punto de entrada de la biblioteca de vínculos dinámicos, por lo que el tipo de operación que la función de punto de entrada puede realizar está restringida. Para obtener más información sobre estas restricciones, consulte Archivos DLL y comportamiento de la biblioteca en tiempo de ejecución de Visual C++ y Punto de entrada de DllMain.
Ejemplo
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 el recuento de referencias del elemento desconocido externo de una agregación.
ULONG OuterAddRef();
Valor devuelto
Valor que puede ser útil para los diagnósticos y las pruebas.
CComObjectRootEx::OuterQueryInterface
Recupera un puntero indirecto a la interfaz solicitada.
HRESULT OuterQueryInterface(REFIID iid, void** ppvObject);
Parámetros
iid
[in] GUID de la interfaz que se solicita.
ppvObject
[out] Puntero al puntero de interfaz especificado en iid o NULL si la agregación no admite la interfaz.
Valor devuelto
Uno de los valores HRESULT estándar.
CComObjectRootEx::OuterRelease
Disminuye el recuento de referencias del elemento desconocido externo de una agregación.
ULONG OuterRelease();
Valor devuelto
En compilaciones que no son de depuración, siempre devuelve 0. En las compilaciones de depuración, devuelve un valor que puede ser útil para los diagnósticos o las pruebas.
CComObjectRootEx::Unlock
Si el modelo de subprocesos es multiproceso, este método llama a la función LeaveCriticalSection de la API de Win32, que libera la propiedad del objeto de sección crítica obtenido mediante un miembro de datos privado.
void Unlock();
Comentarios
Para obtener la propiedad, el subproceso debe llamar a Lock
. Cada llamada a Lock
requiere una llamada correspondiente a Unlock
para liberar la propiedad de la sección crítica.
Si el modelo de subprocesos es de un solo subproceso, este método no hace nada.
Consulte también
CComAggObject (clase)
CComObject (clase)
CComPolyObject (clase)
Información general sobre la clase