0

私は本当にこの問題に固執しています。私はメモリリークのあるアプリケーションを持っています。問題を取り除くには、クラスのデストラクタを呼び出す必要があります。ポリモーフィズムでデストラクタの3つの層を呼び出す

クラスの2層のために

、この問題は簡単ですが、このような状況では、クラスの3つの層がありますし、私はこれをコンパイルするために取得する方法を見つけることができません。

#include<iostream> 

using namespace std; 

/* *MUST* be an abstract class and contains data that must be freed */ 
class C { 
public: 
    virtual ~C()=0; 
}; 

/* Contains concrete methods and contains data that has to be freed */ 
class B:public C { 
public: 
    virtual ~B(); 
}; 

/* contains no data, only methods nothing needs to be freed in here */ 
class A:public B { 
public: 
    ~A(); 
}; 

int main(){ 
    C *c = new A; 
    return 0; 
} 

私はコードIをコンパイルエラーが表示されます。

[email protected] ~ $ gcc deleteme.cpp -std=c++11 
/tmp/cc7nxaw5.o: In function `main': 
deleteme.cpp:(.text+0x12): undefined reference to `operator new(unsigned int)' 
/tmp/cc7nxaw5.o: In function `__static_initialization_and_destruction_0(int, int)': 
deleteme.cpp:(.text+0x4b): undefined reference to `std::ios_base::Init::Init()' 
deleteme.cpp:(.text+0x62): undefined reference to `std::ios_base::Init::~Init()' 
/tmp/cc7nxaw5.o: In function `B::B()': 
deleteme.cpp:(.text._ZN1BC2Ev[_ZN1BC5Ev]+0x16): undefined reference to `vtable for B' 
/tmp/cc7nxaw5.o: In function `A::A()': 
deleteme.cpp:(.text._ZN1AC2Ev[_ZN1AC5Ev]+0x16): undefined reference to `vtable for A' 
/tmp/cc7nxaw5.o:(.rodata._ZTV1C[_ZTV1C]+0x8): undefined reference to `__cxa_pure_virtual' 
/tmp/cc7nxaw5.o:(.rodata._ZTV1C[_ZTV1C]+0xc): undefined reference to `__cxa_pure_virtual' 
/tmp/cc7nxaw5.o:(.rodata._ZTI1C[_ZTI1C]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info' 
collect2: error: ld returned 1 exit status 

誰もがA、BおよびCのデストラクタが全てと呼ばれているように私は、デストラクタを書き換えることができる方法を見つけ出すことはできますか?

私はこの1つで私の髪を裂いている、任意の助けをいただければ幸いです。ただし、コメントや継承階層の要件を変更することはできません。そのためには、アプリケーション全体を書き直す必要があります。

非常に高く評価されています。

編集:質問への以下のコメントのために多くおかげで、である私の作品解決策:

#include<iostream> 

using namespace std; 

/* *MUST* be an abstract class and contains data that must be freed */ 
class C { 
public: 
    virtual ~C()=0; 
}; 

C::~C(){ 
    cout<<"destroying C"<<endl; 
} 

/* Contains concrete methods and contains data that have to be freed */ 
class B:public C { 
public: 
    ~B(); 
}; 

B::~B(){ 
    cout<<"destroying B"<<endl; 
} 

/* contains no data, only methods nothing needs to be freed in here */ 
class A:public B { 
public: 
    ~A(); 
}; 

A::~A(){ 
    cout<<"destroying A"<<endl; 
} 

int main(){ 
    C *c = new A; 
    delete c; 
    return 0; 
} 

おかげであなたのアドバイスのための非常に。

+3

デストラクタの定義を与えてください。おそらくもっとうまくいくでしょう。 '〜B(){}' –

+1

また、 'delete c;'を追加すると、実際にそれらが呼び出されます。スマートポインタを使う。 –

+1

これは私には混乱しています: '/ * *は抽象クラスでなければならず、解放されなければならないデータ* /'と 'virtual〜C()= 0;'を含んでいなければなりません。 'C'は解放するデータを持っています。これを行うには、 'C'だけが十分知っているはずです。 'C'にはデストラクタが必要です。明確化する。純粋な仮想デストラクタを持ち、依然としてデストラクタを提供することができます。奇妙だが、真実。 – user4581301

答えて

1

解決策は、それらを必要とするクラスでデストラクタを実装し、残りの部分をコンパイラに処理させることです。

class C{ 
    int* cp; 

public: 

    C(){ cp = new int;} 

    virtual ~C(){ 
     delete cp; 
     cout << "~C()" << endl; 
    } 

    virtual void someMethod()=0; 
}; 

クラスB、純粋仮想関数を実装して解放する必要のあるデータを持っている必要があります:Cは、このようにデストラクタを取得するよう

まず、Cは、解放する必要のあるいくつかのデータを持っていますだから:

最後に、クラスAはデストラクタを必要としないので、いくつかの方法があります。

class A: public B{ 
    public: 
    virtual ~A(){ 
     cout << "~A()" << endl; 
    } 
}; 

このクラスを構築し、deleteとデストラクタが適切にすべての3つのデストラクタを呼び出します呼び出し:

int main(){ 
    C *c = new A; 
    delete c; 
    return 0; 
} 

出力:

~A() 
~B() 
~C() 

をしかし、私はデモのためにここにも1が含まれますTry it online

メモ:It lあなたが投稿したコードのようなooksは、抽象クラスを作るために純粋な仮想デストラクタの宣言を使用しようとしました。しかし、クラス内のリソースを解放する必要がある場合、あなたは純粋な仮想関数を持っていなければ、その目的のために別の関数を使用する必要があります。

編集:
読書here 1は、純粋な指定子と同じ機能の定義を提供するために実際に有効であることを学ぶことができます - だけでなくデストラクタに適用されます。だから、実際にこれを行うことができます。

class C{ 
    virtual ~C() = 0; 
}; 

C::~C(){ /*Implementation here*/} 

を終わりに、できるだけ早く少なくとも1つの機能は、純粋仮想(=0)あなたのクラスが抽象的です。これがデストラクタであれば、他の関数は問題ではありません。しかし、クラスがリソースを解放する必要がある場合は、デストラクタのボディが必要です。

+0

あなたの答えをありがとう、私はこれから残っていた質問の1つは、デストラクタの仮想継承することができた場合、それはあなたのように見えます。ありがとう非常に:)私は実際のコードベースでこれらのソリューションをテストする必要があります。なぜなら、Cが抽象クラスであることが重要であるからです。多形クラスインスタンスのベクトルがあり、Cが抽象クラスでない場合はPandoras Boxを開きます。 – Owl

+0

この場合、Cは抽象です。抽象化するデストラクタではなく 'someMethod()' – Anedar

+0

です。これは完全に機能します。また、メモリリークを修正しました。ありがとうございました。私は今、メモリリークフリーのニューラルネットワークを持っています! – Owl

関連する問題