0

以下のコードを実行してください:

#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;

class ClassA
{
    protected:
    int width, height;

    public:
  void set_values(int x, int y)
  {
      width = x;
      height = y;
  }
  virtual int area()
  {
      return 100;
  }
  ~ClassA()
  {
      cout << "base class destructor called" << endl;

  }
};

class ClassB : public ClassA
{
    public :
int area()
{
    return (width * height);
}
~ClassB()
{
    cout << "derived class destructor called" << endl;
}
};
int main()
{
  ClassA *Ptr = new ClassB;
  Ptr->set_values(10, 20);
  cout << Ptr->area() << endl;
  delete Ptr;
     return 0;
} 

上記のコードでは、ポインターには派生クラス オブジェクトのアドレスが含まれているため、ポインターを削除するときに基本クラスのデストラクタと共に派生クラスのデストラクタを呼び出す必要がありますが、なぜ基本クラスのデストラクタのみを呼び出すのでしょうか。基本クラスのデストラクタを仮想として作成した場合、派生クラスと基本クラスのデストラクタの両方を呼び出すのはなぜですか? 仮想関数の場合、基本クラスと派生クラスの両方が同じ関数名を持っているため、コンパイラは派生クラスで最も派生したものを解決しますが、ここではデストラクタは同じ名前を持たず、コンパイラが呼び出す必要があるものをどのように解決するか実行中に。方法を説明してください

4

4 に答える 4

3

virtualポリモーフィックな破壊が適切に機能するためには、基本クラスのデストラクタを作成する必要があります。

class ClassA
{
    // ...
    virtual ~ClassA()
//  ^^^^^^^
//  Add this!
    {
        cout << "base class destructor called" << endl;
    }
};

そうしないと、実行時に未定義の動作が発生しdelete Ptrます。

基本クラスのデストラクタを仮想として作成した場合、派生クラスと基本クラスのデストラクタの両方を呼び出すのはなぜですか?

これは、通常のオブジェクト破壊シーケンスの一部です。オブジェクトを破棄すると、そのオブジェクトのクラスのデストラクタが最初に呼び出され、次にそのオブジェクトのすべての非静的クラス メンバーのデストラクタが (宣言の逆順で)、次にすべての基本クラスのデストラクタが呼び出されます。

virtualしたがって、呼び出される最初のデストラクタがオブジェクトの実際のランタイム型のデストラクタであるという意味で (もちろん、基本クラスのデストラクタを作成する場合)、仮想ディスパッチはここで正しく実行されます ( ClassB)。その後、基本クラスのデストラクタClassAが呼び出され、通常の破壊プロセスの一部となります。

ただし、ここではデストラクタの名前が同じではなく、コンパイラが実行時に呼び出す必要があるものを解決する方法

デストラクタは特別なメンバー関数です。各クラスはデストラクタを 1 つしか持つことができないため、それらの名前 (先頭に~文字を追加して、クラスの名前と同じにする必要があります) は関係ありません。コンパイラは、どの関数がデストラクタであるかを認識しています。

于 2013-03-08T11:22:10.600 に答える
2

基本クラスのデストラクタはvirtual.

于 2013-03-08T11:21:46.140 に答える
0

is notであるため、実際には未定義の動作であり、何でも起こり得る。~ClassA()virtual

ClassA *Ptr = new ClassB;
///....
delete Ptr;
于 2013-03-08T11:21:39.647 に答える
0

デストラクタを仮想としてマークする必要があります。そうしないと、コンパイラは最も派生したデストラクタを呼び出すことを知りません。

virtual ~ClassA()
{
    cout << "base class destructor called" << endl;

}
于 2013-03-08T11:21:53.153 に答える