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
  1. using pointer member variables for each interface,
  2. using nested classes, and
  3. using multiple inheritance.

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.
Essential COMEssential COM

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.

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