テンプレート クラス 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 の両方をモジュールに含める必要がないことです。 1 つの CComPolyObject オブジェクトで両方のケースが処理されます。 つまり、モジュールには、vtable の 1 つのコピーと関数の 1 つのコピーのみが存在します。 vtable が大きい場合、これにより、モジュールのサイズが大幅に縮小される可能性があります。 一方、vtable が小さい場合は、CComPolyObject を使用すると、CComAggObject や CComObject のように、集計オブジェクトまたは非集計オブジェクトに合わせて最適化されないため、モジュールのサイズが若干大きくなります。