如何从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);