刚才无聊给自己的的COM组件设了几个断点想看看COM组件的创建过程,发现有些不明白的地方,大家帮忙看看,情况是这样的:
组件的类叫CMath,两个接口ISimpleMath和IAdvanceMath,外加一个类厂CMathFactory,不支持聚合,聚合IUnkown接口传进来直接返回错
调用过程:(省略掉COM环境初始化和释放)
1.调用CoCreateInstance创建COM组件并且用参数查询ISimpleMath接口
2.用得到的ISimpleMath指针调用其中的两个函数IncreamInt和DescreamInt
3.用ISimpleMath指针调用QueryInterface查询IAdvanceMath接口
4.ISimpleMath->Release释放ISimpleMath接口
5.调用IAdvanceMath当中两个函数Add和Minus
6.释放IAdvanceMath接口这个过程当中CoCreateInstance成功跳转到DllGetClassObject创建类厂然后调用CMathFactory::CreateInstance创建CMath对象,并且调用CMath::QueryInstance获取ISimpleMath接口,然后调用CMath::AddRef来增加引用计数,这些都是我程序里写好的很正常,然后按F5继续执行,照理说应该输出两次函数执行后结果然后跳到CMath::QueryInstance来查询IAdvanceMath接口再释放掉ISimpleMath接口。但是事实是他莫名其妙的又跳进CMath::AddRef来增加一个引用计数,然后又跳进CMath::Release来减少引用计数,然后再跳回类厂CMathFactory::Release来减少类厂引用计数并且销毁类厂(这个时候类厂的引用计数已经等于0),然后再跳去CMath::QueryInterface来重新查询ISimpleMath接口并增加引用计数,而从输出上看,到这个时候甚至还没有开始调用ISimpleMath的任何一个函数,后来在CoCreateInstace之后直接加一条cout来输出,结果发现这一切都在CoCreateInstance里面发生。想知道的是为什么CoCreateInstance要去查询这个接口两遍,在这个过程当中COM内部到底发生了什么事情。
另外想问一下的是,按照多继承的原理如果CMath的继承写成CMath:public ISimpleMath,IAdvanceMath{...};而ISimpleMath和IAdvanceMath都写成ISimpleMath:IUnknwon和IAdvance:IUnknwon,那么照理说CMath里应该有两个IUnknwon,那这样的话照《COM技术内幕》那书里写的那样的QueryInterfaceHRESULT __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) ;
trace("Component:\t\tReturn pointer to IX.") ; 
}
else if (iid == IID_IY)
{
*ppv = static_cast<IY*>(this) ; 
trace("Component:\t\tReturn pointer to IY.") ; 
}
else
{
*ppv = NULL ;
return E_NOINTERFACE ;
} reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
return S_OK ;
}会不会有问题?我把它最后那行reinterpret_cast<IUnknown*>(*ppv)->AddRef()改成
static_cast<IUnknown *> (static_cast<IX *> (this))->AddRef();有没有必要?