如何从ATL对象集合中检索对象指针?

如何从ATL对象集合中检索对象指针?

问题描述:

我有一个对象集合,定义为:

I have a collection of objects that is defined as:

typedef IField                  ItemInterface;
typedef CComObject<CField>*     ItemClassPtr;
typedef CAdapt< CComPtr<ItemInterface> > ItemType;
typedef std::vector< ItemType > ContainerType;

我通过一系列调用创建了几个CField对象(忽略hresult) p>

and I have created several of the CField objects via a series of calls (ignoring hresult):

IField* ppField = 0;
hresult = CField::CreateInstance(&ppField);
ItemType spField = ppField;
m_coll.push_back(spField);
ppField->Release();

现在我试图检索一个指针指向一个对象,这样我可以调用它的一个方法:

and now I'm trying to retrieve a pointer to an object so that I can call one of it's methods:

ItemClassPtr pField;
short type1;
m_coll[index].m_T->QueryInterface( __uuidof(ItemInterface), (void **)&pField ) );
pField->get_Type(&type1);

,并且在get_Type调用时违反访问冲突。
这是响应响应者的帖子而改变的:

and it crashes on access violation at the get_Type call. this was changed in response to a responder's post to:

short type1;
IField * ppField = m_coll[index].m_T;
CComQIPtr<CField, &__uuidof(IField)> pField = ppField;
pField->get_Type(&type1);

但在尝试跟踪get_Type调用时,它仍然崩溃。

but it still crashes when I attempt to trace in the get_Type call.

这是CField类定义的序言:

Here is the preamble to the CField class definition:

class ATL_NO_VTABLE CField : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CField, &CLSID_Field>,
    public ISupportErrorInfo,
    public IFieldAccess,
    public IDispatchImpl<IField, &IID_IField, &LIBID_SQLite02>
{
    friend class CFields;
    friend class CrecordSet;
public:
    CField();
    ~CField();

DECLARE_REGISTRY_RESOURCEID(IDR_FIELD)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CField)
    COM_INTERFACE_ENTRY(IField)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(ISupportErrorInfo)
    COM_INTERFACE_ENTRY_IID(__uuidof(IField), CField)
END_COM_MAP()

请帮助!

请注意,此问题是与之前的ATL问题的分支在ICollectionOnSTLImpl实现中,不能访问m_T或项目对象的成员
更完全描述集合类。我已用typedef替换了#defines。

Note that this question is an offshoot from a previous ATL question In ICollectionOnSTLImpl implementation, can't access m_T or item object's members That more fully describes the collection class. I have replaced the #defines with typedefs.

Vance

您不能使用 QueryInterface()获取指针,只能使用接口指针。而且你也不能对类指针的接口指针进行类型转换。访问实现类的唯一安全方法是定义类实现的一个单独的私有接口,并且该接口暴露一个方法,该方法返回类对象的 this 指针。例如:

You can't use QueryInterface() to get a class pointer, only an interface pointer. And you can't type-cast an interface pointer to a class pointer, either. The only safe way to get access to the implementation class is to define a separate private interface that the class implements, and have that interface expose a method that returns the class object's this pointer. For example:

class CField;

interface DECLSPEC_UUID("...") IFieldAccess : public IUnknown
{
public:
    virtual CField* get_ClassPtr() = 0;
};

class ATL_NO_VTABLE CField : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CField, &CLSID_Field>,
    public IDispatchImpl<IField, &IID_IField, &LIBID_SQLite02>,
    public ISupportErrorInfo,
    public IFieldAccess,
{
    friend class CFields;
    friend class CrecordSet;
public:
    CField();
    ~CField();

DECLARE_REGISTRY_RESOURCEID(IDR_FIELD)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CField)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IField)
    COM_INTERFACE_ENTRY(IFieldAccess)
    COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
};

CField* CField::get_ClassPtr()
{
    return this;
}

CComPtr<IFieldAccess> pFieldAccess;
CField* pField;
short type1;
m_coll[index].m_T->QueryInterface( __uuidof(IFieldAccess), (void **)&pFieldAccess) );
pField = pFieldAccess->get_ClassPtr();
pField->get_Type(&type1);