24

Scott は、Effective C++、第 3 版、pg. 43 抽象クラスを作成するには、純粋な仮想デストラクタを与えるだけでよいことがわかりました。

class AWOV {                  // AWOV = "Abstract w/o Virtuals"
public:
  virtual ~AWOV() = 0;        // declare pure virtual destructor
};

それから、彼は続けて、1 つのひねりがあると言いました: 純粋な仮想デストラクタの定義を提供する必要があります:

AWOV::~AWOW() {}              // definition of pure virtual dtor

私の質問は、 を指定することによって= 0、純粋仮想関数の場合、関数は、この純粋仮想関数が宣言されているクラスの定義を持つことができないと言っているということです。

ここで純粋仮想デストラクタの定義を (空であっても) 提供してもよいのはなぜですか?

4

6 に答える 6

14

「この関数は、この純粋仮想関数が宣言されているクラスの定義を持つことはできないと言っています。」

それは純粋な仮想が意味するものではありません。純粋仮想は、含まれているクラスをインスタンス化できない (抽象的である) ことを意味するだけなので、サブクラス化する必要があり、サブクラスはメソッドをオーバーライドする必要があります。例えば、

struct A {
    virtual ~A() = 0;
};

A::~A() {}

struct B : A {};

int main()
{
    A a;  // error
    B b;  // ok
}

ここでは、Bデストラクタが暗黙的に定義されています。それが純粋な仮想の別のメソッドである場合は、明示的にオーバーライドする必要があります。

struct A {
    virtual void foo() = 0;
};

void A::foo() {}

struct B : A {};

int main()
{
    B b;  // error
}

純粋仮想メソッドの定義を提供することは、基本クラスを抽象化する必要があるが、それでも既定の動作を提供する必要がある場合に適しています。

デストラクタの特定のケースでは、サブクラスのインスタンスが破棄されたときに自動的に呼び出されるため、これを提供する必要があります。定義なしで純粋な仮想デストラクタを使用してクラスのサブクラスをインスタンス化しようとするプログラムは、リンカーを渡しません。

于 2012-10-16T15:56:34.450 に答える
7

派生(非抽象)クラスに独自のクラスを実装することを純粋に強制します。

実装を提供すると、派生クラスが基本クラスの動作を呼び出すことができます(デストラクタはデフォルトでこれを行います)。

于 2012-10-16T15:57:28.033 に答える
5

2ケースあります。

純粋仮想デストラクタ

このケースは、規格によって特別に扱われます。

12.4 デストラクタ [class.dtor]

virtual9) デストラクタは(10.3) または純粋virtual(10.4)として宣言できます。そのクラスまたは派生クラスのオブジェクトがプログラムで作成された場合、デストラクタが定義されます。クラスに仮想デストラクタを持つ基底クラスがある場合、そのデストラクタ (ユーザー宣言または暗黙宣言に関係なく) は仮想です。

デストラクタの場合は異なります。すべてのデストラクタは、明示的でなくても、構築の逆の順序で継承階層 (正しい削除を前提として) で呼び出されるためです。したがって、オブジェクトが削除されると、基本クラスのデストラクタが呼び出されます。そのため、実装が必要です。

純粋仮想方式

これらは、実装する必要がなく、実装も必要ないという点でデストラクタとは異なります。欠落している要件の違いは、 aDerived::foo()が呼び出されたときに自動的に呼び出されBase::foo()ないことです (実装できるかできないため、可能であるというわけではありません)。

純粋なvirtualメソッドを実装する理由は、ケースによって異なります。私は純粋な指定子を、ロジックに関連するものではなく、プログラマーへのヒントとして見ています。これは、そのメソッドを実装する必要があることをプログラマーに伝えます。基本クラスに実装があるかどうかは問題ではありません。

= 0 を指定することにより、純粋仮想関数の場合、関数は、この純粋仮想関数が宣言されているクラスの定義を持つことができないと言っています。

あまり。派生した非抽象クラスはその関数をオーバーライドする必要があると言っています。これは、自分で実装することを妨げません。

于 2012-10-16T16:11:26.627 に答える
2

これは、すべての純粋仮想機能に必要なわけではありません。全くない。

このように、派生クラスは引き続き実装を強制的にオーバーライドしますが、呼び出す必要がある場合に備えて、基本クラスにデフォルトの実装があります。これは、デストラクタを扱っているためです。派生オブジェクトが破棄されると、そのデストラクタが呼び出され、その基本クラスのデストラクタも呼び出されます。そのため、 の実装が必要ですA::~A

于 2012-10-16T15:59:27.723 に答える
0

関数を純粋仮想化することにより、クラスのユーザーは派生クラス内の関数を別の関数に置き換える必要があります。

基本クラス関数は引き続き呼び出すことができますBaseClass::myfunction(...)

ここで、基本クラスは、派生クラスが選択した場合に使用できるいくつかのコア機能を提供する必要がある場合があります。

于 2012-10-16T15:59:11.340 に答える