18.4 Virtual destructors, virtual assignment, and overriding virtualization
https://www.learncpp.com/cpp-tutorial/virtual-destructors-virtual-assignment-and-overriding-virtualization/
c++はdefault destructorを提供していますが、自分で作成する必要がある場合があります.
(特にメモリの再割り当てが必要な場合)
継承を処理する場合はdestructorをvirtualにしなければなりません
次の例を示します.
しかし、Derived destructorを呼び出す必要があります.
上記の場合、m arrayは無効になりません.
上記の問題はBase'sdestructorをvirtualに設定して解決できます
Whenever you are dealing with inheritance, you should make any explicit destructors virtual.
virtualdestructorが必要なら
クラスに特別なインプリメンテーションが必要ない場合は、次のように記述できます.
まずこの話題をスキップします.
functionのvirtualを無視しようとする人は少ない
次の例を示します.
このとき
これは新しいプログラマーがよく聞く質問です.メモリの漏洩を防ぐためには、すべてのdestructorに仮想タグを付けることが望ましい.しかし、必ずそうしなければなりませんか?
簡単に言えばそうしましょう.パフォーマンスペナルティはありますが、他のことを考えると、一番適切です
以下説明を省略する
c++はdefault destructorを提供していますが、自分で作成する必要がある場合があります.
(特にメモリの再割り当てが必要な場合)
継承を処理する場合はdestructorをvirtualにしなければなりません
次の例を示します.
#include <iostream>
class Base
{
public:
~Base() // note: not virtual
{
std::cout << "Calling ~Base()\n";
}
};
class Derived: public Base
{
private:
int* m_array;
public:
Derived(int length)
: m_array{ new int[length] }
{
}
~Derived() // note: not virtual (your compiler may warn you about this)
{
std::cout << "Calling ~Derived()\n";
delete[] m_array;
}
};
int main()
{
Derived *derived { new Derived(5) };
Base *base { derived };
delete base;
return 0;
}
main関数では、baseはBase pointerなので、baseが削除されると、Base destructorがvirtualであることがプログラムに表示されます.上のプログラムではBasedestructorはvirtualではないのでBasedestructorのみ呼び出しますしかし、Derived destructorを呼び出す必要があります.
上記の場合、m arrayは無効になりません.
上記の問題はBase'sdestructorをvirtualに設定して解決できます
#include <iostream>
class Base
{
public:
virtual ~Base() // note: virtual
{
std::cout << "Calling ~Base()\n";
}
};
class Derived: public Base
{
private:
int* m_array;
public:
Derived(int length)
: m_array{ new int[length] }
{
}
virtual ~Derived() // note: virtual
{
std::cout << "Calling ~Derived()\n";
delete[] m_array;
}
};
int main()
{
Derived *derived { new Derived(5) };
Base *base { derived };
delete base;
return 0;
}
上記のようにvirtualに設定すると、プログラムは予想通りに実行されます.Rule
Whenever you are dealing with inheritance, you should make any explicit destructors virtual.
virtualdestructorが必要なら
クラスに特別なインプリメンテーションが必要ない場合は、次のように記述できます.
virtual ~Base() = default; // generate a virtual default destructor
default destructorの機能しか必要ありませんがvirtualが必要な場合は上記のように記述しますVirtual assignment
まずこの話題をスキップします.
Ignoring virtualization
functionのvirtualを無視しようとする人は少ない
次の例を示します.
class Base
{
public:
virtual ~Base() = default;
virtual const char* getName() const { return "Base"; }
};
class Derived: public Base
{
public:
virtual const char* getName() const { return "Derived"; }
};
派生オブジェクトを受信したBaseポインタを使用してBase::getName()を呼び出すことができます.このとき
#include <iostream>
int main()
{
Derived derived;
const Base &base { derived };
// Calls Base::GetName() instead of the virtualized Derived::GetName()
std::cout << base.Base::getName() << '\n';
return 0;
}
以上のようにベースBase::範囲識別子オペレータgetName()を使用してBaseのgetName()を呼び出します.Should we make all destructors virtual?
これは新しいプログラマーがよく聞く質問です.メモリの漏洩を防ぐためには、すべてのdestructorに仮想タグを付けることが望ましい.しかし、必ずそうしなければなりませんか?
簡単に言えばそうしましょう.パフォーマンスペナルティはありますが、他のことを考えると、一番適切です
以下説明を省略する
Reference
この問題について(18.4 Virtual destructors, virtual assignment, and overriding virtualization), 我々は、より多くの情報をここで見つけました https://velog.io/@ikmy0ung/18.4-Virtual-destructors-virtual-assignment-and-overriding-virtualizationテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol