B のデストラクタで A にアクセスする安全な方法は何でしょうか? (Aのデストラクタにもいる可能性があるため)。
安全な方法はありません:
3.8/1
[...] T 型のオブジェクトの有効期間は、次の場合に終了します。
— T が非自明なデストラクタ (12.4) を持つクラス型の場合、デストラクタ呼び出しが開始されます [...]
オブジェクトの有効期間が終了すると、オブジェクトにアクセスできないのは簡単だと思います。
編集: Chris Drew がコメントで書いたように、デストラクタが開始された後にオブジェクトを使用できます。申し訳ありませんが、標準の重要な文を 1 つ見逃していました。
3.8/5
オブジェクトの有効期間が開始する前であるが、オブジェクトが占有するストレージが割り当てられた後、またはオブジェクトの有効期間が終了した後、オブジェクトが占有していたストレージが再利用または解放される前に、ストレージを参照するポインターオブジェクトが配置される、または配置された場所を使用できますが、限られた方法でのみ使用できます。建設中または破壊中のオブジェクトについては、12.7 を参照してください。それ以外の場合、そのようなポインターは割り当てられたストレージ (3.7.4.2) を参照し、ポインターが void* 型であるかのようにポインターを使用することは明確に定義されています。このようなポインターは参照解除できますが、結果の左辺値は、以下で説明するように、限られた方法でのみ使用できます。次の場合、プログラムは未定義の動作をします: [...]
12.7 には、構築および破棄中にできることのリストがあり、最も重要なもののいくつかは次のとおりです。
12.7/3:
クラス X のオブジェクトを参照するポインタ(glvalue) を、 Xの直接的または間接的な基底クラス Bへのポインタ (参照) に明示的または暗黙的に変換するには、 X の構築と、その直接的または間接的な基底すべての構築B から直接的または間接的に派生するクラスが開始され、これらのクラスの破棄が完了していない必要があります。そうでない場合、変換は未定義の動作を引き起こします。オブジェクト obj の直接の非静的メンバーへのポインターを形成する (またはその値にアクセスする) には、 objの構築が開始され、その破棄が完了していない必要があります。そうしないと、ポインター値の計算 (またはメンバー値へのアクセス) が未定義の動作になります。
12.7/4
仮想関数 (10.3) を含むメンバー関数は、構築または破棄中に呼び出すことができます(12.6.2)。クラスの非静的データ メンバーの構築中または破棄中を含め、コンストラクタまたはデストラクタから仮想関数が直接的または間接的に呼び出され、呼び出しが適用されるオブジェクトが構築中のオブジェクト (x と呼ぶ) である場合または破壊の場合、呼び出される関数は、コンストラクタまたはデストラクタのクラスの最終オーバーライドであり、より派生したクラスでそれをオーバーライドするものではありません。仮想関数呼び出しが明示的なクラス メンバー アクセス (5.2.5) を使用し、オブジェクト式が x またはその基本クラス サブオブジェクトの 1 つではなく、x またはその基本クラス サブオブジェクトの 1 つの完全なオブジェクトを参照する場合、動作は未定義です。 .