在 COM 中调用 QueryInterface() 是绝对必要的吗?
Is calling QueryInterface() ever absolutely necessary in COM?
在 this C++/COM shell 扩展教程中,程序员演示(出于启迪目的)您可以放弃调用 QueryInterface()
并简单地传递一个通用对象。至少在实施 DllGetClassObject()
时有效。他说 QueryInterface()
的目的只是让每个对象自己说明它是否支持给定的接口。
与此同时,Microsoft 似乎 say 需要 QueryInterface()
才能获得指向对象上特定接口的指针。
那么 QueryInterface()
需要到什么程度呢?有没有什么时候调用 QueryInterface()
是绝对必要的,没有它代码就无法工作?或者如视频教程所建议的那样,获得对象本身在技术上是否足够?
不,作为一般规则,您不能跳过调用 QueryInterface
,除非您知道您拥有的接口指针已经正确。
如果我们想象一个实现 IFoo 和 IBar 的对象,布局可能看起来像这样:
VT
IFoo_QueryInterface(...)
IFoo_AddRef()
IFoo_Release()
IFoo_FooFight(int, int)
VT
IBar_QueryInterface(...)
IBar_AddRef()
IBar_Release()
IBar_BarBarBar(int)
对象的实例可能指向 IFoo
s v-table 指针或 IBar
s v-table 指针。调用第 4 个方法而不知道它到底是哪个方法会崩溃,因为参数计数不相同。即使签名相同,调用任意方法也不是一个好主意。
您所指的视频之所以能成功,只是因为 DllGetClassObject
的来电者通常只要求 IClassFactory
。但即使在那里也不安全,因为有人可能会要求 IClassFactory2
。因此,正确的 DllGetClassObject
实现也应该调用 QueryInterface
.
我建议在学习 COM 基础知识时尝试使用 C 而不是 C++ 编写代码,这会迫使您自己处理所有 v-table 间接寻址。查看 this series 了解详情。
在 this C++/COM shell 扩展教程中,程序员演示(出于启迪目的)您可以放弃调用 QueryInterface()
并简单地传递一个通用对象。至少在实施 DllGetClassObject()
时有效。他说 QueryInterface()
的目的只是让每个对象自己说明它是否支持给定的接口。
与此同时,Microsoft 似乎 say 需要 QueryInterface()
才能获得指向对象上特定接口的指针。
那么 QueryInterface()
需要到什么程度呢?有没有什么时候调用 QueryInterface()
是绝对必要的,没有它代码就无法工作?或者如视频教程所建议的那样,获得对象本身在技术上是否足够?
不,作为一般规则,您不能跳过调用 QueryInterface
,除非您知道您拥有的接口指针已经正确。
如果我们想象一个实现 IFoo 和 IBar 的对象,布局可能看起来像这样:
VT
IFoo_QueryInterface(...)
IFoo_AddRef()
IFoo_Release()
IFoo_FooFight(int, int)
VT
IBar_QueryInterface(...)
IBar_AddRef()
IBar_Release()
IBar_BarBarBar(int)
对象的实例可能指向 IFoo
s v-table 指针或 IBar
s v-table 指针。调用第 4 个方法而不知道它到底是哪个方法会崩溃,因为参数计数不相同。即使签名相同,调用任意方法也不是一个好主意。
您所指的视频之所以能成功,只是因为 DllGetClassObject
的来电者通常只要求 IClassFactory
。但即使在那里也不安全,因为有人可能会要求 IClassFactory2
。因此,正确的 DllGetClassObject
实现也应该调用 QueryInterface
.
我建议在学习 COM 基础知识时尝试使用 C 而不是 C++ 编写代码,这会迫使您自己处理所有 v-table 间接寻址。查看 this series 了解详情。