4

このことを考慮:

class FluffyThing
{
public:
  FluffyThing()
  {
    m_pMyFur = new Fur;
  }
  virtual ~FluffyThing();

protected:
  Fur * m_pMyFur;
};

class ClawedFluffyThing : public FluffyThing
{
public:
  ClawedFluffyThing()
    : FluffyThing()
  {
    m_pMyClaws = new Claws;
  }
  virtual ~ClawedFluffyThing();

protected:
  Claws * m_pMyClaws;
};

class ScaryFluffyThing : public ClawedFluffyThing
{
public:
  ScaryFluffyThing()
    : ClawedFluffyThing()
  {
    m_pMyTeeth = new Teeth;
    m_pMyCollar = new SpikedCollar;
  }
  virtual ~ScaryFluffyThing();

protected:
  Teeth * m_pMyTeeth;
  SpikedCollar * m_pMyCollar;
};

あまり間違いがないことを願っています。重要なポイントは、それらの間に IS-A 関係を持つ 3 つのクラスがあり、各クラスには、破棄時に何らかのクリーンアップが必要になる属性も 1 つまたは 2 つあるということです。仮想デストラクタを宣言していなかった場合、コンパイラは次のものを自動的に生成しますか? デストラクタを宣言したため、(クラスが使用されていると仮定して) それらを実装することを余儀なくされたのは、破壊を行うための正しい長時間の方法に続くものですか?

FluffyThing::~FluffyThing()
{
  delete m_pMyFur;
}

ClawedFluffyThing::~ClawedFluffyThing()
{
  delete m_pMyClaws;
  FluffyThing::~FluffyThing();
}

ScaryFluffyThing::~ScaryFluffyThing()
{
   delete m_pMyTeeth;
   delete m_pMyCollar;
   ClawedFluffyThing::~ClawedFluffyThing();
}

決定的な答えはすでにそこにあるはずです...しかし、私は自分の好みに合わせてすぐにそれを手に入れることができませんでした.

4

1 に答える 1

4

いいえ。基本クラスのデストラクタを手動で呼び出すのではなく、継承の逆順で自動的に呼び出されます。それ以外は問題ありません。

FluffyThing::~FluffyThing()
{
  delete m_pMyFur;
}

ClawedFluffyThing::~ClawedFluffyThing()
{
  delete m_pMyClaws;
} //will call ~FluffyThing

ScaryFluffyThing::~ScaryFluffyThing()
{
   delete m_pMyTeeth;
   delete m_pMyCollar;
}  //will call ~ClawedFluffyThing

もちろん、deleteRAII (生のポインターの代わりにスマート ポインター) を使用した場合は、s も必要ありません。

仮想デストラクタを宣言していなかった場合、コンパイラは次のものを自動的に生成しますか?

いいえ:)virtualデストラクタは、基本クラスのポインタを介して派生クラスのインスタンスを削除する場合の正しい動作のためにあります。以下:

FluffyThing* p = new ScaryFluffyThing;
delete p;

FluffyThingのデストラクタが仮想の場合にのみ有効です。それ以外の場合は、未定義の動作です。

于 2012-08-14T00:54:24.767 に答える