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.
Yes,
std::vector< CComPtr<IChild> >is the way to do it – you will get a dynamic array ofIChild*that manages the lifetime ofIChild-derived objects. Once you want to convert theIChild*to a derived interface you’ll have to useQueryInterface()the same way as you would usedynamic_castwith C++ objects.There’s no point to use
CComQIPtrfor the array. The primary use ofCComQIPtris to have a convenient way to callQueryInterface()on a pointer to an object that maybe implements the interface of interest. Instead of callingQueryInterface()and checking the result you invoke theCComQIPtrconstructor and check whether the resulting object contains a non-null pointer. You could useCComQIPtrin the code that uses your array, but there’s no point in using it for the array itself.