Component Objects: C++ Nested Classes

The next example shows how the same object is declared and initialized using the C++ nested class approach. As in the C example, the nested class declaration includes one data structure for each interface and four private data members: an object-level reference count, two interface pointers, and a pointer to the enclosing object. The private implementations of the IUnknown methods are called by the implementations declared for the derived interfaces. For each interface implementation, there is a structure containing a public constructor and destructor, private declarations of the interface methods, a private pointer to CObj, and an interface-level reference counter for debugging purposes. To allow the nested interface classes to access the private members of the outer class, each interface class is made a friend of the outer class.

The benefits of implementing with C++ nested classes lie in the ability to include initialization code and method implementation inline. However, inline declaration is for the convenience of illustration and is not required.

class  CObj  { 
 
private: 
  ULONG          m_ObjRefCount; 
  LPSTORAGE      m_pStg; 
  LPOLEOBJECT    m_pOleObj; 
  CDOC    *      m_pCDoc; 
 
public: 
  CObj(); 
  ~CObj(); 
 
  struct CUnknown : IUnknown 
{ 
  private: 
  ULONG          m_RefCount; 
  CObj  *        m_pCObj; 
 
  public: 
  CUnknown(CObj (pCObj) 
  { m_pCObj = pCObj; m_RefCount = 0; } 
  HRESULT QueryInterface(REFIID riid, LPVOID  * ppvObj) 
  ULONG AddRef(void) { return ++m_ObjRefCount; } 
  ULONG Release(void); 
} 
friend CUnknown; 
CUnknown m_Unknown; 
 
struct InterfaceA : InterfaceA 
{ 
  private: 
  ULONG          m_RefCount; 
  CObj  *        m_pCObj; 
 
  public: 
  CInterfaceA(CObj *pCObj) 
  { m_pCObj = pCObj; m_RefCount = 0; } 
  HRESULT QueryInterface(REFIID riid, LPVOID  * ppvObj) 
  ULONG AddRef(void) { return ++m_ObjRefCount; } 
  ULONG Release(void); 
  HRESULT MethodA1(LPVOID  * ppvObj); 
  HRESULT MethodA2(DWORD dwArg); 
} 
friend CInterfaceA; 
CInterfaceA m_InterfaceA; 
 
struct InterfaceB : InterfaceB 
{ 
  private: 
  ULONG          m_RefCount; 
  CObj  *        m_pCObj; 
 
  public: 
  CInterfaceB(CObj *pCObj) 
  { m_pCObj = pCObj; m_RefCount = 0; } 
  HRESULT QueryInterface(REFIID riid, LPVOID  * ppvObj) 
  ULONG AddRef(void) { return ++m_ObjRefCount; } 
  ULONG Release(void); 
  HRESULT MethodB1(void); 
  HRESULT MethodB2(DWORD dwArg1, DWORD dwArg2); 
} 
friend CInterfaceB; 
CInterfaceB m_InterfaceB;