实现 CComObject、CComAggObject 和 CComPolyObject
CComObject、CComAggObject 和 CComPolyObject 的模板类始终是继承链中派生最多的类。 他们负责处理 IUnknown
中的所有方法:QueryInterface
、AddRef
和 Release
。 此外,CComAggObject
和 CComPolyObject
(用于聚合对象)提供内部未知所需的特殊引用计数和 QueryInterface
语义。
是否使用 CComObject
、CComAggObject
或 CComPolyObject
取决于是否声明以下宏之一或者不声明任何宏:
宏 | 效果 |
---|---|
DECLARE_NOT_AGGREGATABLE | 请始终使用 CComObject 。 |
DECLARE_AGGREGATABLE | 如果对象聚合,则使用 CComAggObject ;如果不是,则使用 CComObject 。 CComCoClass 包含此宏,因此,如果类中未声明任何DECLARE_*_AGGREGATABLE 宏,则为默认值。 |
DECLARE_ONLY_AGGREGATABLE | 请始终使用 CComAggObject 。 如果未聚合对象,则返回错误。 |
DECLARE_POLY_AGGREGATABLE | 调用 IClassFactory::CreateInstance 时,ATL 将创建 CComPolyObject<CYourClass> 的实例。 在创建过程中,将检查外部未知成员的值。 如果为 NULL,则 IUnknown 为非聚合对象实现。 如果外部未知不为 NULL,则会为聚合对象实现 IUnknown 。 |
使用 CComAggObject
和 CComObject
的优点是实现 IUnknown
针对所创建对象的类型进行了优化。 例如,非聚合对象只需要引用计数,而聚合对象需要内部未知的引用计数和指向外部未知的指针。
使用 CComPolyObject
的优点是,避免在模块中同时使用 CComAggObject
和 CComObject
处理聚合和非聚合情况。 单个 CComPolyObject
对象处理这两种情况。 这意味着模块中只有一个 vtable 副本和一个函数副本。 如果 vtable 很大,这可以大大减小模块大小。 但是,如果 vtable 较小,则使用 CComPolyObject
可能会导致模块大小略大,因为它未针对聚合或非聚合对象进行优化,如 CComAggObject
和 CComObject
所示。