Implementar CComObject, CComAggObject e CComPolyObject

As classes de modelo CComObject, CComAggObject e CComPolyObject são sempre as classes mais derivadas na cadeia de herança. É responsabilidade delas lidar com todos os métodos em IUnknown: QueryInterface, AddRef e Release. Além disso, CComAggObject e CComPolyObject (quando usado para objetos agregados) fornecem a contagem de referências especial e a semântica QueryInterface necessária para o desconhecido interno.

Se CComObject, CComAggObject ou CComPolyObject é usado depende de você declarar uma (ou nenhuma) das seguintes macros:

Macro Efeito
DECLARE_NOT_AGGREGATABLE Sempre usa CComObject.
DECLARE_AGGREGATABLE Usa CComAggObject se o objeto é agregado e CComObject se não é. CComCoClass contém essa macro, portanto, se nenhuma das macros DECLARE_*_AGGREGATABLE for declarada em sua classe, esse será o padrão.
DECLARE_ONLY_AGGREGATABLE Sempre usa CComAggObject. Retorna um erro se o objeto não é agregado.
DECLARE_POLY_AGGREGATABLE A ATL cria uma instância de CComPolyObject<CYourClass> quando IClassFactory::CreateInstance é chamada. Durante a criação, o valor do desconhecido externo é verificado. Se for NULL, IUnknown será implementado para um objeto não agregado. Se o desconhecido externo não for NULL, IUnknown será implementado para um objeto agregado.

A vantagem de usar CComAggObject e CComObject é que a implementação de IUnknown é otimizada para o tipo de objeto que está sendo criado. Por exemplo, um objeto não agregado só precisa de uma contagem de referência, enquanto um objeto agregado precisa de uma contagem de referência para o desconhecido interno e um ponteiro para o desconhecido externo.

A vantagem de usar 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 objeto CComPolyObject manipula os dois casos. Isso significa que apenas uma cópia da vtable e uma cópia das funções existem em seu módulo. Se a vtable for grande, isso poderá diminuir substancialmente o tamanho do módulo. No entanto, se a vtable for pequena, usar CComPolyObject poderá resultar em um tamanho de módulo um pouco maior porque ele não é otimizado para um objeto agregado ou não agregado, como são CComAggObject e CComObject.

Confira também

Princípios básicos de objetos COM da ATL
Macros de fábrica de classes e agregação