tags:

views:

119

answers:

2

I have an ATL COM object which needs to expose a collection of other COM objects, so clients can find out how many objects are in the collection (via a simple Count property which I can provide) and access the objects using its index. This collection of objects is dynamic - the count is not fixed - and I don't know how many there will be when my main (parent) object is constructed (so I can't create these objects in my FinalConstruct for example). The objects I want to expose only have read-only properties.

What I want to do is somehow create a std::vector of these objects the first time they are required. I want to use ATL smart COM pointers where possible so I don't need to manually manage reference counts, etc. but I'm not sure whether I should be using CComPtr, 'CComQIPtr', etc.

Assuming the objects I want to return are called IChild, I was hoping I could do something like this:

std::vector<CComPtr<IChild> > children;
...
CComPtr<IChild> child;
// Somehow instantiate an IChild?
...
children.push_back(child);

STDMETHODIMP Parent::GetAt(LONG index, IChild** pRet)
{
  *pRet = children[index];
}

If anyone has any pointers on how I can achieve this, I would be very welcome. There is an excellent article on exposing a static object, but I can't find anything on the particular problem in hand.

+1  A: 

CComPtr<...> assumes that you assign it a compatible interface. CComQIPtr<...> calls IUnknown::QueryInterface to get the right interface. That's why it takes an additional GUID as a template parameter.

For your purposes, you should go with CComPtr, since you know you will always be initializing entries with an IChild.

MSN
+1  A: 

Yes, std::vector< CComPtr<IChild> > is the way to do it - you will get a dynamic array of IChild* that manages the lifetime of IChild-derived objects. Once you want to convert the IChild* to a derived interface you'll have to use QueryInterface() the same way as you would use dynamic_cast with C++ objects.

There's no point to use CComQIPtr for the array. The primary use of CComQIPtr is to have a convenient way to call QueryInterface() on a pointer to an object that maybe implements the interface of interest. Instead of calling QueryInterface() and checking the result you invoke the CComQIPtr constructor and check whether the resulting object contains a non-null pointer. You could use CComQIPtr in the code that uses your array, but there's no point in using it for the array itself.

sharptooth