2012-02-02 12 views
7

基本クラスBaseのすべての子孫に対してファイナライズメソッドfinalize()を宣言する必要があります。破棄の際に呼び出されるべきで、私の意図は純粋なvirtual void Base::finalize() = 0~Base()から呼び出すことでしたが、C++ではそのようなことは禁じられています。だから私の質問はデストラクタから仮想メソッドを呼び出す - 回避策?

どのように私たちは右と暫定的な方法でいくつかのファイナライズ作業を行うことを約束することができますか?コードがコンパイルできないことを

#include <QDebug> 
class Base { 
     public: 
      Base(){} 
      virtual ~Base(){ 
       qDebug("deleting b"); 
       finalize(); 
      } 
      virtual void finalize() = 0; 

    }; 

class A : public Base 
    { 
    public: 
     A(){} 
     ~A(){} 
     void finalize(){qDebug("called finalize in a");} 
    }; 

    int main(int argc, char *argv[]) 
    { 
     Base *b = new A; 
     delete b; 
    } 

私が作る場合Base::finalize()純粋仮想ではない、それはそれはすでに破壊されているので、子供に派遣することなく、~Base()から呼び出されます。

私は子のデストラクタからfinalize()を呼び出すことができますが、それを強制する方法は疑問です。言い換えれば、私の質問は、Baseクラスの子孫を書く人に、ドキュメントでコメントする以外の方法でファイナライズ方法を使用するように指示することが可能なのでしょうか? :)仮想デストラクタが何

答えて

7

デストラクタは、取得したリソースを解放するのに適切な場所ですが、各クラスは独自のリソースを解放する責任があります。 class Aによって取得されたリソースは、class Baseによって解放されるべきではありません。仮想デストラクタを定義

class Aclass Aオブジェクトを指し示すclass Baseへのポインタを削除するときにデストラクタが呼ばれるように

Base* p = new A; 
delete p; // Both A and Base destructors are sequencially called! 

だからあなただけの各クラス解放する必要があり、適切なリソースの解放を達成するために」内のリソースを可能にするその独自のデストラクタ。

+1

私はそれを参照してください、しかし私の質問です:基本クラスの子孫を書く人々は、ドキュメントでそれをコメントする以外の方法で、ファイナライズ方法を使用するよう義務付けることは可能ですか? :) –

+1

'Base'のデストラクタが呼び出されるまでに、' A'のデストラクタが既に呼び出されているので、 'A'オブジェクトは存在しないので、コンパイラやランタイムエラーが発生する可能性があります'finalize()'メソッドを呼び出すことができます。 –

+1

私はあなたのサンプルコードを使用し、 'Base'に' finalize() 'を定義しました。それはコンパイルされますが、実行から何が得られるか見ることができます。 –

3

タイプ Bのオブジェクトがか B又は Aへのポインタへのポインタからかかわらず、破壊され
class A 
{ 
public: 
    virtual ~A() {} 
}; 

class B : public A 
{ 
public: 
    virtual ~B() {} 
}; 

、両方のデストラクタがされますと呼ばれる。まず、B::~B()、次にA::~A()

+0

@DmitryKachkoは、 'unsubmit'を実行したい各デストラクタで' unsubmit'を呼び出すだけです。 –

+0

確かに私はそれを行うことができますが、Aクラスを基底として使うことはできません。 –

+0

ありがとう回答!どのように私を助けることができますか?私は破壊中にAの子孫のそれぞれで呼び出されるはずのunsubmit()関数を無効にしています。 Unsubmitの実装は、それぞれに異なります。 - –

1

基本クラスのデストラクタをボディで純粋仮想にしてください。これはあなたが望むものとまったく同じです。

+1

なぜ純粋な仮想ですか? –

+0

派生クラスに強制的に宣言して、独自のデストラクタを実装します。 –

+0

ああ、私は基盤が抽象であることを見なかった(おそらく後の編集)。 –

0

なぜBaseのデスコンストラクタを使用しないのですか?それはデストラクタは何のために作られているのですか?

検索をRAIIにして、C++の中で最も優れたものの1つを発見してください。

他の言語を使用していたほとんどの人はこれを発見する必要があります。 C++でのリソース管理は他のほとんどのコンピュータ言語とはまったく異なります

+0

RAIIは彼の質問に何をしなければならないのですか? –

関連する問題