64,266
社区成员
发帖
与我相关
我的任务
分享
你好我, 我翻了不少老帖子, 发现你说的一段话, 有些不懂,所以再请问
问题1:
Coder_Y_Jao在一个老帖子里说:
为了与语言无关的兼容性
_stdcall是大多数语言都支持的调用约定,_thiscall则用于c++的成员函数,需要ECX存储this。
你可能会问,COM都编译成二进制文件了,不都一样保证本身的功能正常,有什么关系呢。
考虑下面的情况,一个不支持_thiscall的语言中,调用某个成员函数参数入栈后,是不可能将this存储在ecx的。
而你编译好的COM(_thiscall)中,则使用这个ecx来间接操作其他成员等,这就导致了不兼容。
而_stdcall则直接push this指针当做参数入栈,COM中也是_stdcall,不需要关心那个ecx,通过栈来间接操作就好了。
如果有一个 com的接口函数内部调用了 _thiscall或者其他 函数调用约定的 函数,那么又如何呢?
问题2: com中的一个语法讨论
class B:public IOtherInterface
{
protected:
ULONG m_Ref;
B();
~B();
HRESULT _stdcall QueryInterface(const IID&iid, void** ppv);
HRESULT _stdcall AddRef();
HRESULT _stdcall Release();
//other interface members
HRESULT _stdcall Otherfunction()p;
HRESUTL Inti();
private:
IUnkown* m_pUnkownInner;
};
以下是 <com原理和应用 >一书提供的实现源码:
HRESULT B: QueryInterface(const IID& iid, void** ppv)
{
if(iid==IID_IUnkown)
{
*ppv=(IUnkown*)this; //转换(1) ,孙子类指针转换为祖父类指针
((IUnkown*)(*ppv)->AddRef();
}
else if(iid==IID_OtherInterface)
{
*ppv=(IOtherInterface*)this; //转换是否多余 (2)
((IOtherInterface*)(*ppv)->AddRef();
}
else if(iid== IID_SomeInterface)
{
return m_pUnkownInner->QueryInterface(iid,ppv);
}
else
{
*ppv=NULL;
return E_NONTERFACE;
}
return S_OK;
}
(1)为什么孙子类的指针可以强行转换为祖父类的, 我记得,只可以转换为父亲类的指针吧?
(2) 转换为父亲类的指针后,由于是虚函数,最终还是调用孙子类的 覆盖的虚函数, 所以 对于转换为(2)是否多余?
if(id==_A)
{
*ppv=(A*)this;//这里报错
((A*)*ppv)->fun();//1
} else if(id==_B)
{
*ppv=(B*)this;//这里正常
((B*)*ppv)->fun();//2
}
else if(id==_C)
{
*ppv=(C*)this;//这里正常
((C*)*ppv)->fun();//3
}
class B:public IOtherInterface
#include <stdio.h>
enum ID{_A,_B, _C};
class A
{
public:
virtual void fun()=0;
};
//B ,C 都不是虚继承! 注意看代码
class B:public A
{
public:
void fun()
{
printf("B\n");
}
};
class C:public A
{
public:
void fun()
{
printf("C\n");
}
};
//D拥有2份A
class D:public B,public C
{
public:
void fun()
{
printf("D\n");
}
void QueryInterface( ID id, void** ppv)
{
if(id==_A)
{
*ppv=(A*)this;
(*ppv)->fun();
} else if(id==_B)
{
*ppv=(B*)this;
*ppv->fun();
}
else if(id==_C)
{
*ppv=(C*)this;
*ppv->fun();
}
}
};
class CA : public IX, public IY
{
...
};
HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{
if(iid == IID_IUnknown)
{
*ppv = static_cast< IX* >(this);
}
else if(iid == IID_IX)
{
*ppv = static_cast< IX* >(this);
}
else if(iid == IID_IY)
{
*ppv = static_cast< IY* >(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast< IUnknown* >(*ppv)->AddRef();
return S_OK;
}