今天我们来分析QueryInterface函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
HRESULT
CDictionary::QueryInterface(
const
IID& iid,
void
**ppv)
{
if
(iid == IID_IUnknown)
{
*ppv = (IDictionary*)
this
;
((IDictionary*)(*ppv))->AddRef();
}elseif(iid == IID_Dictionary)
{
*ppv = (IDictionary*)
this
;
((IDictionary*)(*ppv))->AddRef();
}elseif(iid == IID_SpellCheck)
{
*ppv = (ISpellCheck*)
this
;
((ISpellCheck*)(*ppv))->AddRef();
}
else
{
*ppv = NULL;
return
E_NOINTERFACE;
}
return
S_OK;
}
|
根据COM接口的内存接口以及C++语言中类多重继承的内存结构,我们实现QueryInterface函数。
QueryInterface函数对于iid的三种可能值分别进行了处理,不管客户要想查询字典对象所支持的哪个接口,QueryInterface都会返回相应的接口指针,如图,当我们将this指针转换为基类指针时,所得到的指针正好指向接口的vtable,所以我们用类型转换函数就可以得到每个接口的vtable,也就是接口指针。
在第一个if语句块中,我们并没有把this指针直接转换为IUnknown指针,根据C++语法,由于在CDictionary的基类树中,有两个IUnknown节点,因此直接把this指针转换成IUnknown指针存在二义性。
先把this指针转换成IDictionary或者ISpellCheck,再转换成IUnknown,但必须保证每次查到的IUnknown接口完全一致。
这个程序直接把IDictionary接口指针当做IUnknown接口指针,这样的转换是符合COM规范的。
根据CDictionary的基类树,这里的继承关系不能用虚拟继承,否则就不能保证IDictionary和ISpellCheck的vtable与COM接口的vtable的一致性。
本文转自 liam2199 博客,原文链接: http://blog.51cto.com/liam2199 如需转载请自行联系原作者