なぜデストラクタだけが仮想関数をつけなければ、サブクラスのデストラクタが発動しないのか。(オーバーライドしていないのになぜ?)
どなたかわかりやすい説明をお願いします(´;ω;`)
継承時にスーパークラスに仮想関数をつける理由
Re: 継承時にスーパークラスに仮想関数をつける理由
agunesu さんが書きました: ↑5年前なぜデストラクタは仮想関数をつけなければ、サブクラスのデストラクタが発動しないのか。(コンストラクタには不要で、オーバーライドしていないのになぜ?)
どなたかわかりやすい説明をお願いします(´;ω;`)
Re: 継承時にスーパークラスに仮想関数をつける理由
質問が不明確なので確認します。
プログラミング言語は C++ ですか?
スーパークラス、サブクラスという名称は Java の用語です。
C++ では、基底クラス、派生クラスという用語が一般的です。
C++ の規格書ににもそう書かれています。まあ、親クラス、
子クラスなどということもあるので意味は分かります。
「仮想関数をつける」というのが不明確です。
おそらく
「メンバ関数に virtual を付けると仮想関数になる」
または、
「virtual のついたメンバ関数は仮想関数である」
ということなのでしょう。クラスにおいて、
コンストラクタやデストラクタは特殊なメンバ関数です。
「デストラクタが発動する」というのも
クラスのインスタンス(オブジェクト)解体時に
デストラクタが自動的に呼び出されるという意味なんでしょうね。
質問を上手く書けない時は、サンプルコードを書き添えることを
お勧めします。
実行結果
★の行で virtual がないときの実行結果
質問は、「基底クラスのデストラクタに virtual を付けないと
派生クラスのデストラクタが呼び出されないのはなぜですか?」
ということですね。
回答は、「それが、C++ の言語仕様だから」としか言えません。
new Derived() でオブジェクトを生成しているので
コンストラクタの Base() も Derived() も呼び出されます。
delete p でそのオブジェクトを解体しようとすると、
p が Baseクラスへのポインタなので、~Base() が呼び出されます。
デストラクタに virtual がついていると、~Base() の呼出しの前に
~Derived() が 呼び出されます。
派生クラスのデストラクタと、基底クラスのデストラクタの両方が
呼び出されるということです。
デストラクタではなく、通常のメンバ関数の場合は、少し異なります。
virtual がないと、基底クラスのメンバ関数だけの呼び出しになり、
virtual があると、派生クラスのメンバ関数だけの呼び出しになります。
virtual があっても、「p->Base::メンバ関数()」と書けば、
基底クラスのメンバ関数を呼び出せます。
以上、分かりやすい説明だったでしょうか?
分かった場合も分からない場合も返信をお願いいたします。
プログラミング言語は C++ ですか?
スーパークラス、サブクラスという名称は Java の用語です。
C++ では、基底クラス、派生クラスという用語が一般的です。
C++ の規格書ににもそう書かれています。まあ、親クラス、
子クラスなどということもあるので意味は分かります。
「仮想関数をつける」というのが不明確です。
おそらく
「メンバ関数に virtual を付けると仮想関数になる」
または、
「virtual のついたメンバ関数は仮想関数である」
ということなのでしょう。クラスにおいて、
コンストラクタやデストラクタは特殊なメンバ関数です。
「デストラクタが発動する」というのも
クラスのインスタンス(オブジェクト)解体時に
デストラクタが自動的に呼び出されるという意味なんでしょうね。
質問を上手く書けない時は、サンプルコードを書き添えることを
お勧めします。
#include <stdio.h>
struct Base {
Base() { puts("Base()"); }
virtual ~Base() { puts("~Base()"); } // ★
};
struct Derived : public Base {
Derived() { puts("Derived()"); }
~Derived() { puts("~Derived()"); }
};
int main()
{
Base *p = new Derived();
delete p;
}
派生クラスのデストラクタが呼び出されないのはなぜですか?」
ということですね。
回答は、「それが、C++ の言語仕様だから」としか言えません。
new Derived() でオブジェクトを生成しているので
コンストラクタの Base() も Derived() も呼び出されます。
delete p でそのオブジェクトを解体しようとすると、
p が Baseクラスへのポインタなので、~Base() が呼び出されます。
デストラクタに virtual がついていると、~Base() の呼出しの前に
~Derived() が 呼び出されます。
派生クラスのデストラクタと、基底クラスのデストラクタの両方が
呼び出されるということです。
デストラクタではなく、通常のメンバ関数の場合は、少し異なります。
virtual がないと、基底クラスのメンバ関数だけの呼び出しになり、
virtual があると、派生クラスのメンバ関数だけの呼び出しになります。
virtual があっても、「p->Base::メンバ関数()」と書けば、
基底クラスのメンバ関数を呼び出せます。
以上、分かりやすい説明だったでしょうか?
分かった場合も分からない場合も返信をお願いいたします。
Re: 継承時にスーパークラスに仮想関数をつける理由
大変わかりやすい説明ありがとうございましたm(_ _)m
自分が説明不十分だったのに的確の説明でした(笑)
今度からもっと詳しく書き込みたいと思います。
どうもありがとうございました<(_ _)>
自分が説明不十分だったのに的確の説明でした(笑)
今度からもっと詳しく書き込みたいと思います。
どうもありがとうございました<(_ _)>
Re: 継承時にスーパークラスに仮想関数をつける理由
大変わかりやすい説明ありがとうございましたm(_ _)m
自分が説明不十分だったのに的確の説明でした(笑)
今度からもっと詳しく書き込みたいと思います。
どうもありがとうございました<(_ _)>
自分が説明不十分だったのに的確の説明でした(笑)
今度からもっと詳しく書き込みたいと思います。
どうもありがとうございました<(_ _)>