This article about techniques of reusing COM objects in client application or in another COM object. To understand it you have to know some basics of COM and ATL, mostly you have to know what is
IUnknown interface and it's methods (
QueryInerface(), AddRef(),Release()), and how a simple ATL object works and is implemented. So first you can take a look at articles in CodeProject about basics of ATL.
Object Reuse in C++
As you know there are two way of reusing an existing class in C++, Containment and Inheritance.Containment is declaration of an object within a class scope.Let's take a look at an example:
You can see that
CMyClass contains an instance of the pre-existing "
CBaseclass" and it can control access to the
Another technique is Inheritance:
class CMyClass public CBaseClass
Here you have access to public and protected member functions of
CBaseclass as the member of
Ok, I know that you know all these things so let's talk about COM
COM supports containment but it does not support inheritance in the way that C++ does.In the example above
CMyClass inherits functionality implemented by the
CBaseclass.The public or protected member functions of the
CBaseclass are available to the
CMyClass.This kind of inheritance is known as implementation inheritance.
Now take a look at an example of inheritance in COM:
What's the difference?
By deriving one interface from another,you specify the structure of the vtable that will hold pointer to the instantiated methods. In the example above it means
IMyInterface, besides having its own methods, has three function of
IUnknown interface too:
There is nothing the same as virtual function you see in C++ and MFC. Here,
QueryInterface method of
IUnknown interface, if you want another
QueryInterface method you have to implement
IUnknown interface yourself and change
QueryInterface of it,and then inherit
IMyInterface from your own
IUnknown interface. This kind of inheritance is called Interface inheritance.Clear? Hmm!
Containment is having one component as a member variable of another.(Do you remember the containment in C++?) The outer (controlling,containing) component makes use of the inner(contained) component,but does not directly expose the contained component to its client. The outer component manage the lifetime of the inner component. It creates the inner component with
CoCtreateInstance() when it initializes itself(in
FinalConstruct()), and releases the inner component's interface pointer when it uninitialize itself (in
FinalRelease()). I can say outer component isn't doing anything very different from what a standard client would do.
In aggregation the interface of the inner object directly expose to the client without collection of wrapper.A client creates the outer object and when it asks
QueryInterface() for an interface supported by the inner object, it gets passed a pointer to the inner object's interface.
One advantage of aggregation over containment is that it requiers much less knowledge of the inner component on the part of the person implementing the outer component.Another is that bypassing the wrapper layer makes the component that bit more efficient.
The disadvantage of aggregation is that the inner object can only be implemented in a DLL that is directly loaded into the same apartment as the outer object.There is no cross-apartment,cross-process or cross-machine aggregation.
For aggregation to work ,the inner object must be aggregatable ,it must be written to support aggregation. To be aggregatable,the inner component must have two distinc implementations of the three
Release().One version is called non-delegating and is used by outer object,another one is called delegating which used by client.(Because the client of the outer object can now obtian interface pointers exposed by the inner object)
Aggregation can be used to perform the 'black box' reuse of code.You can view 'black box' reuse from two perspectives: First,the outer object is adding functionality to the inner object,or else it's purposely creating the inner object to implement one or more interfaces.In both cases ,the identity of the composite object is the outer object,the outer object can aggregate many different objects,each with their own identities,but they will be combined into one single object with one identity.
It can be useful to write objects aggregatable.Doing so has no effect at all on the object's instrinsic usefulness, but it'll increase size of code a little(the COM runtime,for example).
Aggregation is a little bit complicated topic,although the ATL wizard handles the hard parts of aggregation for you.
- Beginning ATL3 COM Programming by Dr.Richard Grimes
- Desktop application with Microsoft Visual C++6.0 MCSD Training Kit