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
, InternalQueryInterface
InternalAddRef
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 macroIUnknown
.Substitua
FinalRelease
para liberar oIUnknown
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