COM Aggregation   «Prev  Next»
Lesson 7Aggregation guidelines: inner objects
Objective List the guidelines for aggregated inner objects.

Aggregation Guidelines Inner Objects

To support aggregation, a COM object must provide an implementation that supports the following guidelines.

Nondelegating IUnknown

A COM object implements an object-level IUnknown interface. This means the inner object implements an IUnknown interface that is separate and distinct from other COM interfaces in the object. In COM literature, this is called the nondelegating IUnknown. The nondelegating IUnknown performs normal IUnknown functionality. This guideline requires each COM object that supports aggregation to provide a separate, object-level, IUnknown implementation, that is, the nondelegating IUnknown. The outer COM object will use the nondelegating IUnknown to retrieve interfaces from the inner object and to release the inner object. The nondelegating IUnknown is not visible to the client.

Delegating IUnknown

The IUnknown methods in all interfaces exposed by the inner COM object to the client as part of the aggregation (that is, all QueryInterface, AddRef, and Release methods except those in the object-level IUnknown) must not perform any interface navigation or reference counting. Instead, they must delegate all calls into the outer object's IUnknown. In COM literature, this type of IUnknown is called a delegating IUnknown because it delegates all functionality to the outer object's IUnknown.
This guideline supports interface navigation and reference counting across multiple objects in the aggregation by centralizing all IUnknown functionality in the outer COM object. This allows the outer COM object's IUnknown to control interface navigation and reference counting on all interfaces, in all aggregated objects.
We will discuss how the inner object gets the outer object's IUnknown pointer in a subsequent lesson.
Implementing nondelegating and delegating IUnknown interfaces with multiple inheritance requires you to specify a stand-alone IUnknown interface.

Nondelegating and delegating IUnknown

The following code fragments demonstrate how to add a nondelegating IUnknown into a COM object implementation that uses multiple inheritance. Assume that the outer object's IUnknown pointer is passed into a constructor of CCOMObj.

//Specify interface IA
class IA : public IUnknown {
  virtual HRESULT __stdcall A1() = 0;
};

//Specify interface IB
class IB : public IUnknown {
  virtual HRESULT __stdcall B1() = 0;
};

Specify a standalone IUnknown interface to be the non-delegating IUnknown. Its methods must use different names to avoid name conflicts with the IUnknown methods in other interfaces. This is OK since COM calls are based on vtable position and not names. Don't inherit from IUnknown. Doing so will force the method names to be QueryInterface, AddRef, and Release.
class INonDelegatingIUnknown {   
 virtual HRESULT __stdcall objQueryInterface
 (REFIID riid, VOID **ppv) = 0;
 virtual ULONG __stdcall objAddRef() = 0;
 virtual ULONG __stdcall objRelease() = 0;
};

class CCOMObj : INonDelegatingIUnknown, IA, IB {
 private:
  ULONG m_refcnt;
  IUnknown *m_pIOuterIUnknown;
 public:
  //INonDelegatingIUnknown methods
  HRESULT objQueryInterface(REFIID riid, VOID **ppv);  
  ULONG objAddRef();
  ULONG objRelease();
  //IUnknown methods for IA and IB
  HRESULT QueryInterface(REFIID riid, VOID **ppv);
  ULONG AddRef();
  ULONG Release();
  //IA methods
  HRESULT A1();
  //IB methods
  HRESULT B1();
  /* Assume that the outer object's IUnknown pointer 
	is passed into the constructor */
  CCOMObj(IUnknown *pOuter) : m_refcnt(0), 
	m_pIOuterIUnknown(NULL) {
    m_pIOuterIUnknown = pOuter;
  }
};
Additionally, this interface must use different names (but the same function attributes and parameter types) for QueryInterface, AddRef, and Release to avoid name conflicts with the IUnknown members of other interfaces.
The following diagram shows a COM object with nondelegating and delegating IUnknown interfaces.
Non-delegating IUnknown interfaces : obQueryInterface, objAddRef, objRelease
Non-delegating IUnknown interfaces : obQueryInterface, objAddRef, objRelease

Aggregation - Exercise

Click the Exercise link below to apply what you have learned about aggregation guidelines. Aggregation - Exercise