Dynamic array of COM objects
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
f开发者_如何学Cor 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 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.
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
.
精彩评论