Basic COM  «Prev  Next»
Lesson 9Implementing COM objects
ObjectiveDefine a C++ implementation class using multiple inheritance.

Implementing COM objects

In previous lessons we used C++ classes to define COM interfaces, and looked at how to specify COM interfaces in IDL and the C++ class definitions created by compiling IDL files with MIDL. Our next step is to study the standard development paradigms used to develop COM objects in C++. In practice, three standard mechanisms are used. They all define one C++ class to implement a COM object. They differ in how the object's interfaces are handled.
Several conventions have emerged for C++ implementations of COM objects.
These are using pointer member variables for each interface.

I. Creating COM objects using member pointers to interfaces

To create COM objects using member pointers to interfaces:
  1. Define a concrete class for each of the object's interfaces.
  2. Add member variables that are pointers to each class.
  3. Within your COM object's class code, manage these classes.
For example:

class CIMyComInterface : public IMyComInterface{
  provide implementations of all pure
    virtual methods in IMyComInterface
 
};
class CIYourComInterface : public IYourCominterface{
   provide implementations of all pure
     virtual methods in IYourComInterface  
};
class CMyComObject{
   CIMyComInterface    *m_pim;
   CIYourComInterface *m_piy;
   …
};

The member pointers to each COM interface can be instantiated when the COM object is created or on demand when one of the interfaces is requested. The main advantage of this technique is that most developers are familiar with using member pointers to other classes.
Essential COM

II. Creating COM Objects with nested Classes

using nested classes, and usingmultiple inheritance.

Creating COM objects with nested Classes

To create COM objects with nested classes:
  1. Define each COM interface, within the COM object, as a nested class.
  2. Declare a member variable for each class.
For example:

class CMyComObject{
  class CIMyComInterface : public IMyComInterface 
  {
    provide implementations of all pure
    virtual methods in IMyComInterface     
  }
  CIMyComInterface m_im;

  class CIYourComInterface : public IYourComInterface { 
    provide implementations of all pure
    virtual methods in IYourComInterface     
  }
  CIYourComInterface m_iy;
};

The advantage of this method is that the implementation of the COM class reflects the COM containment relationship, for example the COM interfaces are contained in the COM object.

Our main interest is in using multiple inheritance because this is what ATL uses.

Using multiple inheritance

To use multiple inheritance, create a C++ implementation class for your COM object that inherits from the interface specifications in MyComInterface.h (the MIDL-generated include file from previous lessons):

class CMyComObject : public IMyComInterface,
  public IYourComInterface
{
   …
};

Class CMyComObject must implement all methods from IMyComInterface and IYourComInterface. Recall that each COM interface class is defined, either manually or via IDL, to inherit from (i.e. implement) IUnknown - QueryInterface, AddRef, and Release. At first glance it would seem that we need to implement the IUnknown methods twice - once for IMyComInterface and once for IYourComInterface. Doing so would cause a name conflict because we can not implement two identical methods with the same signature in a C++ class. The following code fragment demonstrates how we handle this situation.

class CMyComObject : public IMyComInterface,
  public IYourComInterface {
   HRESULT __stdcall QueryInterface
     (const IID& iid, void **ppv);
  
   ULONG __stdcall AddRef();
   ULONG __stdcall Release();

   //Methods for IMyComInterface
     - excluding IUnknown
  
   HRESULT __stdcall Fx1(CHAR *buf);
   HRESULT __stdcall Fx2();

   //Methods for IYourComInterface
     - excluding IUnknown
  
   HRESULT __stdcall Zx1(LONG ix);
};

When the Visual C++ compiler sees both base classes defining the methods with the same signature, it expects only one implementation of these methods in the derived class. The compiler actually generates two vtables within the CMyComObject class object, one for each interface. The IUnknown entries of each vtable point to the shared methods. We do not need to specify each function as virtual because the base classes do this.

CLSID

Like COM interfaces, COM objects are identified by a 128-bit ID or UUID. When used to identify a COM object, the IDs are called CLSIDs. The DEFINE_GUID macro can be used to define a variable representing a CLSID.
Clients and objects have different views of a COM object and its interfaces. The object sees the interface implementation via its internal C++ class. The client views the object through its interfaces, that is, its vtables.

Implement Com 0bject - Exercise

Click the Exercise link below to apply what you have learned about implementation of a COM object using multiple inheritance.
Implement Com 0bject - Exercise

.NET COM Complete Interoperability