CComObject、CComAggObject 和 CComPolyObject 的模板类始终是继承链中派生最多的类。 他们负责处理 IUnknown 中的所有方法:QueryInterface、AddRef 和 Release。 此外,CComAggObject 和 CComPolyObject(用于聚合对象)提供内部未知所需的特殊引用计数和 QueryInterface 语义。
是否使用 CComObject、CComAggObject 或 CComPolyObject 取决于是否声明以下宏之一或者不声明任何宏:
| Macro | 效果 |
|---|---|
| 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 所示。