Classe CComObjectRootEx

Essa classe fornece métodos para manipular o gerenciamento de contagem de referência de objeto para objetos não agregados e agregados.

Sintaxe

template<class ThreadModel>
class CComObjectRootEx : public CComObjectRootBase

Parâmetros

ThreadModel
A classe cujos métodos implementam o modelo de threading desejado. Você pode escolher explicitamente o modelo de Threading definindo ThreadModel como CComSingleThreadModel, CComMultiThreadModelou CComMultiThreadModelNoCS. Você pode aceitar o modelo de thread padrão do servidor definindo ThreadModel como CComObjectThreadModel ou CComGlobalsThreadModel.

Membros

Métodos

Função Descrição
CComObjectRootEx Construtor.
InternalAddRef Incrementa a contagem de referência para um objeto não agregado.
InternalRelease Decrementa a contagem de referência para um objeto não agregado.
Bloquear Se o modelo de thread for multi-threaded, o obterá a propriedade de um objeto de seção crítica.
Automático Se o modelo de thread for multi-threaded, o liberará a propriedade de um objeto de seção crítica.

Métodos CComObjectRootBase

Função Descrição
FinalConstruct Substitua em sua classe para executar qualquer inicialização exigida pelo seu objeto.
FinalRelease Substitua em sua classe para executar qualquer limpeza exigida pelo seu objeto.
OuterAddRef Incrementa a contagem de referência para um objeto agregado.
OuterQueryInterface Delega para a externa IUnknown de um objeto agregado.
OuterRelease Decrementa a contagem de referência para um objeto agregado.

Funções estáticas

Função Descrição
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 Descrição
m_dwRef Com m_pOuterUnknown o, parte de uma União. Usado quando o objeto não é agregado para manter a contagem de referência de AddRef e Release .
m_pOuterUnknown Com m_dwRef o, parte de uma União. Usado quando o objeto é agregado para manter um ponteiro para o desconhecido externo.

Comentários

CComObjectRootEx manipula o gerenciamento de contagem de referência de objeto para objetos não agregados e agregados. Ela conterá a contagem de referências de objetos se o objeto não estiver sendo agregado e manterá o ponteiro para o desconhecido externo se o objeto estiver sendo agregado. Para objetos agregados, CComObjectRootEx os métodos podem ser usados para lidar com a falha do objeto interno a ser construído e para proteger o objeto externo da exclusão quando interfaces internas são liberadas ou o objeto interno é excluído.

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

Se a definição de classe especificar a macro DECLARE_POLY_AGGREGATABLE , a ATL criará uma instância de quando IClassFactory::CreateInstance for chamada. Durante a criação, o valor da externa Unknown é verificado. Se for NULL, IUnknown será implementado para um objeto não agregado. Se o desconhecido externo não for nulo, IUnknown será implementado para um objeto agregado.

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

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

Se o objeto for agregado, IUnknown será implementado pelo ou CComPolyObject . Essas classes delegam QueryInterface , AddRef , e Release chamam para ' CComObjectRootEx s OuterQueryInterface , OuterAddRef e OuterRelease para encaminhar para o desconhecido externo. Normalmente, você substitui CComObjectRootEx::FinalConstruct em sua classe para criar qualquer objeto agregado e substituir CComObjectRootEx::FinalRelease para liberar todos os objetos agregados.

Se o objeto não for agregado, IUnknown será implementado pelo CComObject ou CComPolyObject . Nesse caso, as chamadas para QueryInterface , AddRef , e Release são delegadas a CComObjectRootEx , InternalQueryInterfaceInternalAddRef e InternalRelease para executar as operações reais.

Requisitos

Cabeçalho: atlcom. h

CComObjectRootEx::CComObjectRootEx

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

CComObjectRootEx();

CComObjectRootEx::FinalConstruct

Você pode substituir esse método em sua classe derivada para executar qualquer inicialização necessária para seu objeto.

HRESULT FinalConstruct();

Valor Retornado

Retorne S_OK em caso de êxito ou um dos valores HRESULT de erro padrão.

Comentários

Por padrão, o CComObjectRootEx::FinalConstruct simplesmente retorna S_OK.

Há vantagens em executar a inicialização em FinalConstruct vez do construtor de sua classe:

  • Não é possível retornar um código de status de um construtor, mas você pode retornar um HRESULT por meio do FinalConstruct valor de retorno. Quando os objetos da sua classe estão sendo criados usando a fábrica de classes padrão fornecida pela ATL, esse valor de retorno é propagado de volta para o cliente COM, permitindo que você forneça informações detalhadas sobre o erro.

  • Você não pode chamar funções virtuais por meio do mecanismo de função virtual do construtor de uma classe. Chamar uma função virtual do construtor de uma classe resulta em uma chamada resolvida estaticamente para a função conforme ela é definida nesse ponto na hierarquia de herança. Chamadas para funções virtuais puras resultam em erros de vinculador.

    Sua classe não é a classe mais derivada na hierarquia de herança — que depende de uma classe derivada fornecida pela ATL para fornecer algumas de suas funcionalidades. Há uma boa chance de que sua inicialização precise usar os recursos fornecidos pela classe (isso certamente é verdade quando os objetos de sua classe precisam agregar outros objetos), mas o Construtor em sua classe não tem como acessar esses recursos. O código de construção para sua classe é executado antes que a classe mais derivada seja totalmente construída.

    No entanto, FinalConstruct é chamado imediatamente depois que a classe mais derivada é totalmente construída, permitindo que você chame funções virtuais e use a implementação de contagem de referência fornecida pela ATL.

Exemplo

Normalmente, substitua esse método na classe derivada de CComObjectRootEx para criar qualquer objeto agregado. 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, você poderá retornar um erro. Você também pode usar a macro DECLARE_PROTECT_FINAL_CONSTRUCT para proteger seu objeto externo de ser excluído se, durante a criação, o objeto agregado interno incrementar a contagem de referência, e decrementar a contagem para 0.

Aqui está uma maneira típica de criar uma agregação:

  • Adicione um IUnknown ponteiro ao seu objeto de classe e inicialize-o como NULL no construtor.

  • Substitua FinalConstruct para criar a agregação.

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

  • Substitua FinalRelease para liberar o IUnknown ponteiro.

CComObjectRootEx::FinalRelease

Você pode substituir esse método em sua classe derivada para executar qualquer limpeza necessária para seu objeto.

void FinalRelease();

Comentários

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

Executar a limpeza no FinalRelease é preferível a adicionar código ao destruidor de sua classe, pois o objeto ainda está totalmente construído no ponto em que FinalRelease é chamado. Isso permite que você acesse com segurança os métodos fornecidos pela classe mais derivada. Isso é particularmente importante para a liberação de qualquer objeto agregado antes da exclusão.

CComObjectRootEx::InternalAddRef

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

ULONG InternalAddRef();

Valor Retornado

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

Comentários

Se o modelo de thread for multi-threaded, InterlockedIncrement será usado para impedir que mais de um thread altere a contagem de referência 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
no Um ponteiro para o objeto que contém o mapa COM de interfaces expostas para QueryInterface .

pEntries
no Um ponteiro para a _ATL_INTMAP_ENTRY estrutura que acessa um mapa de interfaces disponíveis.

IID
no O GUID da interface que está sendo solicitada.

ppvObject
fora Um ponteiro para o ponteiro de interface especificado em IIDou NULL se a interface não for encontrada.

Valor Retornado

Um dos valores de HRESULT padrão.

Comentários

InternalQueryInterface somente lida com interfaces na tabela de mapa COM. Se o objeto for agregado, o não InternalQueryInterface delegará para o desconhecido externo. Você pode inserir interfaces na tabela de mapa com com a macro COM_INTERFACE_ENTRY ou uma de suas variantes.

CComObjectRootEx::InternalRelease

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

ULONG InternalRelease();

Valor Retornado

Em compilações de não depuração e depuração, essa função retorna um valor que pode ser útil para diagnóstico ou teste. O valor exato retornado depende de muitos fatores, como o sistema operacional usado, e pode ou não ser a contagem de referência.

Comentários

Se o modelo de thread for multi-threaded, InterlockedDecrement será usado para impedir que mais de um thread altere a contagem de referência ao mesmo tempo.

CComObjectRootEx:: Lock

Se o modelo de thread for multi-threaded, esse método chamará a função de API do Win32 EnterCriticalSection, que aguarda até que o thread possa assumir a propriedade do objeto de seção crítica obtido por meio de um membro de dados privado.

void Lock();

Comentários

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

Se o modelo de thread for de thread único, esse método não fará nada.

CComObjectRootEx:: m_dwRef

Parte de uma União que acessa quatro bytes de memória.

long m_dwRef;

Comentários

Com m_pOuterUnknown o, parte de uma União:

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Se o objeto não for agregado, a contagem de referência acessada pelo AddRef e Release será armazenada em m_dwRef . Se o objeto for agregado, o ponteiro para o desconhecido externo será armazenado em m_pOuterUnknown.

CComObjectRootEx:: m_pOuterUnknown

Parte de uma União que acessa quatro bytes de memória.

IUnknown*
    m_pOuterUnknown;

Comentários

Com m_dwRef o, parte de uma União:

union {
    long m_dwRef;
    IUnknown* m_pOuterUnknown;
};

Se o objeto for agregado, o ponteiro para o desconhecido externo será armazenado em m_pOuterUnknown . Se o objeto não for agregado, a contagem de referência acessada pelo AddRef e Release será armazenada em AddRef.

CComObjectRootEx:: ObjectMain

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

static void WINAPI ObjectMain(bool bStarting);

Parâmetros

bStarting
fora O valor será TRUE se a classe estiver sendo inicializada; caso contrário, FALSE.

Comentários

O valor do parâmetro bStarting indica se o módulo está sendo inicializado ou encerrado. A implementação padrão de ObjectMain não faz nada, mas você pode substituir essa função em sua classe para inicializar ou limpar os recursos que deseja alocar para a classe. Observe que ObjectMain é chamado antes de qualquer instância da classe ser solicitada.

ObjectMain é chamado a partir do ponto de entrada da DLL, portanto, o tipo de operação que a função de ponto de entrada pode executar é restrito. Para obter mais informações sobre essas restrições, consulte DLLs e Visual C++ o comportamento da biblioteca de tempo de execução e DllMain.

Exemplo

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 externo de uma agregação.

ULONG OuterAddRef();

Valor Retornado

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

CComObjectRootEx::OuterQueryInterface

Recupera um ponteiro indireto para a interface solicitada.

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

Parâmetros

IID
no O GUID da interface que está sendo solicitada.

ppvObject
fora Um ponteiro para o ponteiro de interface especificado em IIDou NULL se a agregação não oferecer suporte à interface.

Valor Retornado

Um dos valores de HRESULT padrão.

CComObjectRootEx::OuterRelease

Decrementa a contagem de referência do desconhecido externo de uma agregação.

ULONG OuterRelease();

Valor Retornado

Em compilações não depuradas, sempre retorna 0. Em compilações de depuração, retorna um valor que pode ser útil para diagnóstico ou teste.

CComObjectRootEx:: desbloquear

Se o modelo de thread for multi-threaded, esse método chamará a função de API do Win32 LeaveCriticalSection, que libera a propriedade do objeto de seção crítica obtido por meio de um membro de dados privado.

void Unlock();

Comentários

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

Se o modelo de thread for de thread único, esse método não fará nada.

Confira também

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