オブジェクトの破棄

提供: Appmethod Topics
移動先: 案内検索

RTL に対する言語サポート(C++) への移動


オブジェクトの破棄に関わる 2 種類のメカニズムは C++ と Object Pascal で動作が異なります。 これらのメカニズムは次のとおりです。

  • コンストラクタから送出された例外のために呼び出されるデストラクタ
  • デストラクタから呼び出される仮想メソッド

VCL スタイルの各クラスはこれら 2 つの言語のメソッドを結合します。 問題を次に説明します。

コンストラクタから送出される例外

オブジェクトの構築中に例外が送出される場合は、デストラクタの呼び出しは C++ と Object Pascal で異なります。 例として、クラス A から派生したクラス B、そこからさらに派生するクラス C を考えます。

class   A 
{ 

// bod y 
} ; 

class  B:  public   A 
{ 

// bod y 
} ; 

class  C:  public   B 
{ 

// bod y 
} ; 


C のインスタンスを構築時にクラス B のコンストラクタで例外が発生する場合を考えます。C++、Object Pascal、VCL スタイルの各クラスにおける結果を次に説明します。

  • C++ では、まず B のオブジェクト データ メンバで構築が完了したすべての対象のデストラクタが呼び出され、次に A のデストラクタが呼び出され、A のデータ メンバで構築が完了したすべての対象のデストラクタが呼び出されます。 ただし、B と C のデストラクタは呼び出されません。
  • Object Pascal では、インスタンス化クラスのデストラクタだけが自動的に呼び出されます。 これは C のデストラクタです。コンストラクタの場合と同様に、デストラクタで派生クラスを、プログラマが呼び出すことが必要です。 この例では、すべてのデストラクタが派生クラスを呼び出すと仮定すると、C、B、A のデストラクタがこの順序で呼び出されます。 さらに、例外が発生する前に、B のコンストラクタで派生クラスが呼び出されたかどうかに関係なく、A のデストラクタが呼び出されます。派生クラスが B のデストラクタで呼び出されているからです。 A のデストラクタの呼び出しは、そのコンストラクタが実際に呼び出されたかどうかに関係ありません。 さらに重要なことは、派生クラスをすぐに呼び出すことはコンストラクタで共通なので、C のデストラクタはそのコンストラクタ本体の実行が完了したかどうかに関係なく呼び出されます。
  • VCL スタイル クラスでは、VCL の基底(Object Pascal に実装)は、呼び出すデストラクタの Object Pascal メソッドに従います。 派生クラス(C++ に実装)はどちらの言語のメソッドにも正確には従いません。 発生することは、すべてのデストラクタが呼び出されることです。ただし、C++ 言語の規則に従って、呼び出されなかったデストラクタ本体には、入りません。

Object Pascal で実装されたクラスはしたがって、デストラクタ本体でユーザーが記述した任意のクリーンアップ コードを処理する機会があります。 これに含まれるのは、コンストラクタの例外が発生する前に、構築されたサブオブジェクト(オブジェクトであるデータ メンバ)のメモリを解放するコードです。 VCL スタイルのクラスでは、デストラクタを呼び出す場合でも、インスタンス化クラス、または C++ で実装された基底クラスに対してクリーンアップ コードが処理されない可能性があることに注意してください。

デストラクタから呼び出される仮想メソッド

デストラクタでディスパッチする仮想メソッドは、コンストラクタで実行された同じパターンに従います。 つまり、VCL スタイルのクラスに対して、派生クラスが最初に破棄されるが、オブジェクトの実行時型は、基底クラスのデストラクタに対する後続の呼び出し中は、派生クラスの型のままです。 したがって、仮想メソッドが VCL 基底クラスのデストラクタで呼び出される場合は、それ自体を既に破棄されたクラスにユーザーがディスパッチする可能性があります。

関連項目