Partilhar via


Classe CComObjectRootEx

Observação

A Active Template Library (ATL) continua a ser suportada. No entanto, já não estamos a adicionar funcionalidades nem a atualizar a documentação.

Esta classe fornece métodos para gerir a contagem de referências de objetos tanto para objetos não agregados como agregados.

Sintaxe

template<class ThreadModel>
class CComObjectRootEx : public CComObjectRootBase

Parâmetros

ThreadModel
A classe cujos métodos implementam o modelo de threading desejado. Pode escolher explicitamente o modelo de threading definindo o ThreadModel para CComSingleThreadModel, CComMultiThreadModel, ou CComMultiThreadModelNoCS. Pode aceitar o modelo de thread predefinido do servidor definindo o ThreadModel para CComObjectThreadModel ou CComGlobalsThreadModel.

Membros

Methods

Função Description
CComObjectRootEx Construtor.
InternoAddRef Incrementa a contagem de referências para um objeto não agregado.
InternalRelease Diminui a contagem de referência para um objeto não agregado.
Bloqueio Se o modelo de thread for multithread, obtém a propriedade de um objeto de secção crítico.
Desbloquear Se o modelo de thread for multithread, liberta-se a propriedade de um objeto de secção crítico.

Métodos CComObjectRootBase

Função Description
FinalConstruct Sobrescreve na tua classe para realizar qualquer inicialização exigida pelo teu objeto.
FinalLançamento Anule a sua classe para realizar qualquer limpeza exigida pelo seu objeto.
OuterAddRef Incrementa a contagem de referências para um objeto agregado.
OuterQueryInterface Delega para o exterior IUnknown de um objeto agregado.
OuterRelease Diminui a contagem de referência para um objeto agregado.

Funções estáticas

Função Description
InternalQueryInterface Delega para o IUnknown de um objeto não agregado.
ObjectMain Chamado durante a inicialização e terminação do módulo para classes derivadas listadas no mapa de objetos.

Membros de Dados

Membro de dados Description
m_dwRef Com m_pOuterUnknown, parte de um sindicato. Usado quando o objeto não é agregado para conter a contagem de referência de AddRef e Release.
m_pOuterUnknown Com m_dwRef, parte de um sindicato. Usado quando o objeto é agregado para conter um ponteiro para o desconhecido exterior.

Observações

CComObjectRootEx gere a contagem de referências de objetos tanto para objetos não agregados como agregados. Ele mantém a contagem de referências do objeto se o seu objeto não estiver a ser agregado, e mantém o ponteiro para o desconhecido exterior se o seu objeto estiver a ser agregado. Para objetos agregados, CComObjectRootEx podem ser usados métodos para lidar com a falha do objeto interior na construção e para proteger o objeto exterior da eliminação quando as interfaces internas são libertadas ou o objeto interior é eliminado.

Uma classe que implementa um servidor COM deve herdar de CComObjectRootEx ou CComObjectRoot.

Se a sua definição de classe especificar a macro DECLARE_POLY_AGGREGATABLE , o ATL cria uma instância de CComPolyObject<CYourClass> quando IClassFactory::CreateInstance é chamado. Durante a criação, verifica-se o valor do desconhecido exterior. Se for NULL, IUnknown é implementado para um objeto não agregado. Se o desconhecido exterior não for NULL, IUnknown é implementado para um objeto agregado.

Se a sua classe não especificar o macro DECLARE_POLY_AGGREGATABLE, o ATL cria uma instância de CAggComObject<CYourClass> para objetos agregados ou uma instância de CComObject<CYourClass> para objetos não agregados.

A vantagem de usar CComPolyObject é que evitas ter ambos CComAggObject no CComObject módulo para lidar com os casos agregados e não agregados. Um único CComPolyObject objeto trata ambos os casos. Portanto, existem apenas uma cópia da vtable e uma cópia das funções no seu módulo. Se a sua vtable for grande, isso pode diminuir substancialmente o tamanho do seu módulo. No entanto, se a sua vtable for pequena, a utilização CComPolyObject pode resultar num tamanho ligeiramente maior do módulo porque não está otimizada para um objeto agregado ou não agregado, tal como são CComAggObject e CComObject.

Se o seu objeto for agregado, IUnknown é implementado por CComAggObject ou CComPolyObject. Estas classes delegam QueryInterface, AddRef, e Release chamam a CComObjectRootEx, , OuterQueryInterfaceOuterAddRef, e OuterRelease a encaminhar para o desconhecido exterior. Normalmente, sobrescreves CComObjectRootEx::FinalConstruct na tua classe para criar quaisquer objetos agregados, e CComObjectRootEx::FinalRelease sobreescreves para libertar quaisquer objetos agregados.

Se o seu objeto não for agregado, IUnknown é implementado por CComObject ou CComPolyObject. Neste caso, chamadas para QueryInterface, , e Release são delegadas a CComObjectRootEx, InternalAddRefInternalQueryInterface, e InternalRelease para realizar as AddRefoperações reais.

Requerimentos

Cabeçalho: atlcom.h

CComObjectRootEx::CComObjectRootEx

O construtor inicializa a contagem de referência para 0.

CComObjectRootEx();

CComObjectRootEx::FinalConstruct

Pode sobrescrever este método na sua classe derivada para realizar qualquer inicialização necessária para o seu objeto.

HRESULT FinalConstruct();

Valor de retorno

Devolve S_OK em caso de sucesso ou de um dos valores padrão de erro HRESULT.

Observações

Por defeito, CComObjectRootEx::FinalConstruct simplesmente devolve S_OK.

Existem vantagens em realizar a inicialização em FinalConstruct vez do construtor da sua classe:

  • Não pode devolver um código de estado de um construtor, mas pode devolver um HRESULT por meio do FinalConstructvalor de retorno de . Quando objetos da sua classe estão a ser criados usando a fábrica de classes padrão fornecida pelo ATL, este valor de retorno é propagado de volta ao cliente COM, permitindo-lhe fornecer informações detalhadas de erro.

  • Não se podem chamar funções virtuais através do mecanismo de funções virtuais a partir do construtor de uma classe. Chamar uma função virtual a partir do construtor de uma classe resulta numa chamada resolvida estaticamente à função tal como está definida nesse ponto da hierarquia de herança. Chamadas a funções puramente virtuais resultam em erros de linker.

    A sua classe não é a mais derivada na hierarquia de herança — depende de uma classe derivada fornecida pelo ATL para fornecer alguma da sua funcionalidade. Há uma boa hipótese de a sua inicialização precisar de usar as funcionalidades fornecidas por essa classe (isto é certamente verdade quando os objetos da sua classe precisam de agregar outros objetos), mas o construtor na sua classe não tem forma de aceder a essas características. O código de construção da sua classe é executado antes de a classe mais derivada estar totalmente construída.

    No entanto, FinalConstruct é chamado imediatamente após a classe mais derivada estar totalmente construída, permitindo chamar funções virtuais e usar a implementação de contagem de referências fornecida pelo ATL.

Example

Normalmente, sobrepõe-se este método na classe derivada de CComObjectRootEx para criar quaisquer objetos agregados. Por exemplo:

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 a construção falhar, pode devolver um erro. Também pode usar o DECLARE_PROTECT_FINAL_CONSTRUCT macro para proteger o seu objeto exterior de ser eliminado se, durante a criação, o objeto agregado interno incrementar a contagem de referência e depois decrementá-la para 0.

Aqui está uma forma típica de criar um agregado:

  • Adiciona um IUnknown ponteiro ao teu objeto de classe e inicializa-o como NULL no construtor.

  • Override FinalConstruct para criar o agregado.

  • Use o IUnknown ponteiro que definiu como parâmetro para a macro COM_INTERFACE_ENTRY_AGGREGATE .

  • Override FinalRelease para libertar o IUnknown apontador.

CComObjectRootEx::FinalRelease

Pode sobrescrever este método na sua classe derivada para realizar qualquer limpeza necessária para o seu objeto.

void FinalRelease();

Observações

Por defeito, CComObjectRootEx::FinalRelease não faz nada.

Fazer limpeza em FinalRelease é preferível a adicionar código ao destruidor da sua classe, pois o objeto ainda está totalmente construído no ponto em que FinalRelease é chamado. Isto permite-lhe aceder de forma segura aos métodos fornecidos pela classe mais derivada. Isto é particularmente importante para libertar quaisquer objetos agregados antes da eliminação.

CComObjectRootEx::InternalAddRef

Incrementa a contagem de referência de um objeto não agregado em 1.

ULONG InternalAddRef();

Valor de retorno

Um valor que pode ser útil para diagnóstico e testes.

Observações

Se o modelo de thread for multithread, InterlockedIncrement é usado para evitar que mais do que uma thread altere a contagem de referências ao mesmo tempo.

CComObjectRootEx::InternalQueryInterface

Recupera um ponteiro para a interface solicitada.

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

Parâmetros

pThis
[dentro] Um apontador para o objeto que contém o mapa COM das interfaces expostas a QueryInterface.

pEntradas
[dentro] Um apontador para a _ATL_INTMAP_ENTRY estrutura que acede a um mapa das interfaces disponíveis.

IID
[dentro] O GUID da interface a ser solicitada.

ppvObject
[fora] Um ponteiro para o ponteiro da interface especificado no iid, ou NULL se a interface não for encontrada.

Valor de retorno

Um dos valores padrão do HRESULT.

Observações

InternalQueryInterface apenas trata de interfaces na tabela de mapas COM. Se o seu objeto for agregado, InternalQueryInterface não delega ao desconhecido exterior. Pode introduzir interfaces na tabela de mapas COM com a COM_INTERFACE_ENTRY macro ou uma das suas variantes.

CComObjectRootEx::InternalRelease

Diminui a contagem de referência de um objeto não agregado por 1.

ULONG InternalRelease();

Valor de retorno

Tanto em compilações sem depuração como em compilações de depuração, esta função devolve um valor que pode ser útil para diagnósticos ou testes. O valor exato devolvido depende de muitos fatores, como o sistema operativo utilizado, e pode, ou não, ser a contagem de referência.

Observações

Se o modelo de thread for multithread, InterlockedDecrement é usado para evitar que mais do que uma thread altere a contagem de referências ao mesmo tempo.

CComObjectRootEx::Lock

Se o modelo de thread for multithread, este método chama a função API Win32 EnterCriticalSection, que espera até que a thread possa assumir a propriedade do objeto crítico de secção obtido através de um membro privado de dados.

void Lock();

Observações

Quando o código protegido termina de ser executado, a thread deve chamar Unlock para libertar a propriedade da secção crítica.

Se o modelo de thread for single-thread, este método não faz nada.

CComObjectRootEx::m_dwRef

Parte de uma união que acede a quatro bytes de memória.

long m_dwRef;

Observações

Com m_pOuterUnknown, parte de uma união:

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Se o objeto não for agregado, a contagem de referência acedida por AddRef e Release é armazenada em m_dwRef. Se o objeto for agregado, o ponteiro para o desconhecido exterior é armazenado em m_pOuterUnknown.

CComObjectRootEx::m_pOuterUnknown

Parte de uma união que acede a quatro bytes de memória.

IUnknown*
    m_pOuterUnknown;

Observações

Com m_dwRef, parte de uma união:

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Se o objeto for agregado, o ponteiro para o desconhecido exterior é armazenado em m_pOuterUnknown. Se o objeto não for agregado, a contagem de referência acedida por AddRef e Release é armazenada em m_dwRef.

CComObjectRootEx::ObjectMain

Para cada classe listada no mapa de objetos, esta função é chamada uma vez quando o módulo é inicializado e outra quando é terminado.

static void WINAPI ObjectMain(bool bStarting);

Parâmetros

bInício
[fora] O valor é VERDADEIRO se a classe estiver a ser inicializada; caso contrário, FALSO.

Observações

O valor do parâmetro bStarting indica se o módulo está a ser inicializado ou terminado. A implementação padrão de ObjectMain não faz nada, mas podes sobrescrever esta função na tua classe para inicializar ou limpar recursos que queres alocar para a classe. Note que ObjectMain é chamado antes de qualquer instância da classe ser solicitada.

ObjectMain é chamado a partir do ponto de entrada da DLL, pelo que o tipo de operação que a função de entrada pode realizar é restringido. Para mais informações sobre estas restrições, veja DLLs e comportamento de bibliotecas em tempo de execução Visual C++ e DllMain.

Example

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 a contagem de referência do desconhecido exterior de uma agregação.

ULONG OuterAddRef();

Valor de retorno

Um valor que pode ser útil para diagnóstico e testes.

CComObjectRootEx::OuterQueryInterface

Recupera um ponteiro indireto para a interface solicitada.

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

Parâmetros

IID
[dentro] O GUID da interface a ser solicitada.

ppvObject
[fora] Um ponteiro para o ponteiro de interface especificado em iid, ou NULL se a agregação não suportar a interface.

Valor de retorno

Um dos valores padrão do HRESULT.

CComObjectRootEx::OuterRelease

Diminuição da contagem de referência do desconhecido exterior de uma agregação.

ULONG OuterRelease();

Valor de retorno

Em builds que não são de depuração, devolve sempre 0. Em compilações de depuração, devolve um valor que pode ser útil para diagnóstico ou testes.

CComObjectRootEx::Unlock

Se o modelo de thread for multithread, este método chama à função API Win32 LeaveCriticalSection, que liberta a propriedade do objeto crítico de secção obtido através de um membro privado de dados.

void Unlock();

Observações

Para obter a propriedade, o thread deve chamar Lock. Cada chamada para Lock requer uma chamada correspondente para Unlock libertar a propriedade da secção crítica.

Se o modelo de thread for single-thread, este método não faz nada.

Consulte também

Classe CComAggObject
Classe CComObject
Classe CComPolyObject
Visão geral da classe