C++ の仮想デストラクタ

C No Fan Xiangdesutorakuta



C++ は、プログラミングの基本概念の基礎を固め、プログラマーの論理的思考を強化するために使用される言語です。 C++ では、OOP はクラスのオブジェクトを作成するオブジェクト指向言語であるため、OOP は重要な役割を果たします。 OOP では、クラスとオブジェクトを学習します。クラスには、さまざまな型とさまざまなメンバー関数の変数であるデータ メンバーが含まれます。インスタンスの助けを借りて、あらゆるクラスのデータにアクセスします。クラスを作成するとき、すべてのクラスにはコンストラクタとデストラクタがあります。コンストラクターは、そのクラスのオブジェクトが作成されるときに呼び出されます。コンストラクター内でクラスの変数を初期化することもできます。デストラクタもコンストラクタで自動的に作成されますが、デストラクタはオブジェクトを破棄し、オブジェクトを破棄する前に呼び出される最後の関数です。クラスの名前、たとえば「Profession」クラスが作成されます。そのコンストラクタは Profession() で、デストラクタは ~Profession () です。 3人は同じ名前です。

OOP、コンストラクタ、およびデストラクタについて説明した後、仮想デストラクタについて説明しましょう。名前が示すように、仮想デストラクタはオブジェクトを破棄します。基本クラスと、基本クラスから派生した派生クラスがあります。どちらのクラスにもコンストラクタとデストラクタがあります。仮想デストラクタは、「virtual」キーワードを使用して基底クラス ポインタを使用して派生クラスのオブジェクトを削除しながら、派生クラス オブジェクトを通じて割り当てられた記憶を解放します。

仮想デストラクタを使用する理由

クラス メンバー関数の実行が完了するか、main() メソッドの実行が終了しようとしているときに、デストラクタが自動的に呼び出され、オブジェクトの作成中に割り当てられたメモリが解放されます。では、なぜ仮想デストラクタを使用するのでしょうか。派生クラスを指す基底クラスが削除されると、ここでポインター (*) が使用されます。基本クラスのデストラクタは、このプロセス中にのみ呼び出されます。派生クラスのデストラクタが呼び出されないため、問題が発生します。そのうちの 1 つはメモリ リークの問題です。この問題を回避してコードを安全にするために、基本クラスのデストラクタを削除することにより、オブジェクトを仮想的に破棄して、オブジェクトの作成中に割り当てられたメモリ領域を解放します。

仮想デストラクタを使用しない C++ の基本的な例

ポインタを削除する単純なプログラムを使用して、仮想デストラクタなしでプログラムがどのように機能するかを見てみましょう。

コード:

#include

名前空間 std の使用 ;
クラス Parent_Class0
{
公共 :
Parent_Class0 ( )
{ カウト << 「親クラスのコンストラクター」 << エンドル ; }
~Parent_Class0 ( )
{ カウト << 「親クラスのデストラクタ」 << エンドル ; }
} ;
クラス Child_1 : public Parent_Class0
{
公共 :
子_1 ( )
{ カウト << 「子クラスのコンストラクタ」 << エンドル ; }
〜子_1 ( )
{ カウト << 「子クラスのデストラクタ」 << エンドル ; }
} ;
整数 主要 ( )
{
Parent_Class0 * ポインター = 新しい子_1 ( ) ;
ポインタを削除 ;
戻る 0 ;
}

このコードは、仮想デストラクタなしでコードがどのように実行されるかを説明しています。まず、親クラスとなる「Parent_Class0」という名前のクラスを作成します。このクラス内で、コンストラクタとデストラクタを作成します。ご存じのとおり、コンストラクタとデストラクタはクラスと同じ名前です。デストラクタはコンストラクタと同様に表されますが、コンストラクタと区別する記号 (~) があります。コンストラクタとデストラクタ内で、「cout<<」を使用してメッセージを出力します。ここで、「Child_1」という別のクラスを作成します。このクラスは、親クラス「Parent_Class0」から派生します。派生クラスには、出力画面に出力するメッセージを含むコンストラクターとデストラクターがあります。

main() メソッドでは、「Parent_Class0」のインスタンスを作成し、それに派生クラスを割り当てます。この場合に覚えておくべき重要な点は、ポインターを使用して親クラスを取得することです。親クラスの内部に入ると、親クラスのコンストラクターが実行されます。次に、子クラスに移動し、そのコンストラクターを実行します。子クラスのデストラクタを実行する前に、親クラスのデストラクタを実行する必要があります。コンパイラは、親クラスのデストラクタを実行し、子クラスのデストラクタを実行せずにクラスを終了します。それは問題;子のクラスのメモリは解放されません。親クラスのコンストラクタ、子クラスのコンストラクタ、親クラスのデストラクタを表します。これは、子クラスのデストラクタが実行されていないことを示しています。この実行後、main() 関数内のポインターを削除します。

出力:

仮想デストラクタを使用した C++ の例

仮想デストラクタがある場合とない場合の動作を区別するための簡単なコードを使用して、仮想デストラクタについて説明しましょう。

コード:

#include

名前空間 std の使用 ;
クラス Parent_Class0
{
公共 :
Parent_Class0 ( )
{ カウト << 「親クラスのコンストラクタ」 << エンドル ; }
仮想 ~Parent_Class0 ( )
{ カウト << 「親クラスのデストラクタ」 << エンドル ; }
} ;
クラス Child_1 : public Parent_Class0
{
公共 :
子_1 ( )
{ カウト << 「子クラスコンストラクター」 << エンドル ; }
仮想 ~Child_1 ( )
{ カウト << 「子クラスのデストラクタ」 << エンドル ; }
} ;
整数 主要 ( )
{
Parent_Class0 * ポインタ = 新しい子_1 ( ) ;
ポインタを削除 ;
戻る 0 ;
}

最初のプログラムは、仮想デストラクタなしで直面している問題を説明しました。さて、このコードは仮想デストラクタを使用してその問題を解決します。まず、最初のコードをコピーして、このプログラムの 2 か所に 1 つのキーワードを追加するだけです。その言葉は「バーチャル」です。親クラス「Parent_Class0」のデストラクタとともにこの単語を挿入します。同様に、親クラスから派生した子クラスのデストラクタ「Child_1」でこれを記述します。この「virtual」キーワードは少し変更され、「Child_1」子クラスのデストラクタが最初に実行されます。次に、親クラス「Parent_Class0」のデストラクタを実行します。プログラムの残りの部分は、仮想デストラクタなしで動作する場合と同じように動作します。この小さなコードを追加することで、メモリのリークを防ぐことができます。これで、コンソールに 4 つのメッセージが表示されます。最初に親クラスのコンストラクタ、次に子クラスのコンストラクタ、子クラスのデストラクタ、親クラスのデストラクタです。最後に、main() メソッド内のポインターを削除します。

出力:

純粋な仮想デストラクタの C++ の例

このコードでは、純粋な仮想デストラクタ、その仕組み、および仮想デストラクタとの違いについて説明します。

コード:

#include

クラス Parent_0 {
公共 :
仮想 ~Parent_0 ( ) = 0 ;
} ;
親_0 :: ~Parent_0 ( )
{
標準 :: カウト << 「こんにちは、私はピュア・デストラクタです。あなたは私を呼んだ!」 ;
}
クラス Child_0 : public Parent_0 {
公共 :
~Child_0 ( ) { 標準 :: カウト << 「派生デストラクタはこちら \n ' ; }
} ;

整数 主要 ( )
{
親_0 * ptr_0 = 新しい子_0 ( ) ;
ptr_0 を削除 ;
戻る 0 ;
}

親クラス「Parent_0」は、コードの最初のステップで作成されます。その中で、仮想親デストラクタを作成し、それに 0 を割り当てます。これにより、仮想デストラクタが純粋な仮想デストラクタに設定されます。つまり、親クラスは抽象クラスになり、このクラスのインスタンスを作成できなくなります。親クラス「Parent_0」の外で、デストラクタと std::cout を定義します。必要なテキストは、std::cout を利用して表示されます。次に、親クラスから「Child_0」クラスを派生させ、そのデストラクタを定義します。デストラクタ内で、メッセージを出力します。 main() 関数で、親クラスのポインターを作成し、それに子クラスを割り当てます。

コンパイラは、親クラス「Parent_0」に移動します。ポインターが作成されると、そのコンストラクターが自動的に呼び出されます。次に、コンパイラは子クラスに入り、そのコンストラクターを呼び出します。コンストラクタの実行が成功すると、子クラス「Child_0」のデストラクタが実行されます。次に、親クラスのデストラクタを実行します。このようにして、純粋な仮想デストラクタを作成できます。このメソッドを使用すると、親クラスが抽象化されて役に立たなくなるため、使用することはお勧めしません。主に使用される方法論は仮想デストラクタであり、これは優れた方法です。

出力:

結論

仮想デストラクタについて、OOP の概念から始まり、コンストラクタとデストラクタに移行するまでを学びました。これらすべてを説明した後、コーディング例と純粋な仮想デストラクタを使用して、仮想デストラクタについて詳しく説明しました。仮想デストラクタについて説明する前に、コンストラクタ、デストラクタ、および継承について知っておく必要があります。継承では、親クラスからクラスを継承します。子クラスは複数存在できますが、親クラスは 1 つだけです。仮想デストラクタと純粋仮想デストラクタが継承に適用され、メモリ リークが回避されます。基本的な例から高度な例まで、使用を開始して派生クラスのメモリを仮想的に破壊するために知っておくべきことをすべて説明しました。