CComObject、CComAggObject、および CComPolyObject の実装
テンプレート クラス CComObject、CComAggObject、および CComPolyObject は、常に継承チェインの最派生クラスになります。 すべてのメソッドで処理する責任はIUnknown:QueryInterface, AddRef, and Release. また、CComAggObject と CComPolyObject は、集約オブジェクトに使用された場合、内部オブジェクトの IUnknown に必要な特別な参照カウントと QueryInterface を提供します。
CComObject、CComAggObject、または CComPolyObject のうち、どのテンプレート クラスが使用されるかは、以下のどのマクロを宣言するか (あるいはどれも宣言しない) によって異なります。
マクロ |
効果 |
---|---|
DECLARE_NOT_AGGREGATABLE |
常に CComObject を使用します。 |
DECLARE_AGGREGATABLE |
集約オブジェクトの場合は CComAggObject を使用します。非集約オブジェクトの場合は CComObject を使用します。 CComCoClass にはこのマクロが含まれるため、クラスでどの DECLARE_*_AGGREGATABLE マクロも宣言されない場合は、このクラスが既定値になります。 |
DECLARE_ONLY_AGGREGATABLE |
常に CComAggObject を使用します。 非集約オブジェクトの場合はエラーを返します。 |
DECLARE_POLY_AGGREGATABLE |
ATL では、IClassFactory::CreateInstance が呼び出されると、CComPolyObject<CYourClass> のインスタンスが作成されます。 インスタンスの作成時には、外側の IUnknown の値がチェックされます。 値が NULL の場合、IUnknown は非集約オブジェクト用に実装されます。 外側の IUnknown が NULL でない場合、IUnknown は集約オブジェクト用に実装されます。 |
CComAggObject と CComObject を使用する利点は、IUnknown の実装が、作成されるオブジェクトの種類に合わせて最適化されることです。 たとえば、非集約オブジェクトには、参照カウントだけが必要です。一方、集約オブジェクトには、内部オブジェクトの IUnknown の参照カウントと、外側の IUnknown へのポインターの両方が必要です。
CComPolyObject を使用する利点は、集約クラスと非集約クラスを処理するときに、モジュールに CComAggObject と CComObject の両方を持つ必要がないことです。 CComPolyObject オブジェクトが 1 つあれば両方を扱うことができます。 つまり、モジュール中には vtable のコピーと関数のコピーがそれぞれ 1 つだけ存在することになります。 vtable のサイズが大きい場合は、これによってモジュール サイズを大幅に縮小できます。 ただし、vtable のサイズが小さい場合は、CComPolyObject を使うとモジュール サイズが逆に大きくなってしまう可能性があります。これは、CComAggObject や CComObject とは異なり、CComPolyObject は集約オブジェクトや非集約オブジェクト用に最適化されていないためです。