Виртуален деструктор в C++

Virtualen Destruktor V C



C++ е езикът, който се използва, за да даде основа на основната концепция на програмирането и прави логическото мислене на програмистите силно. В C++ ООП играе жизненоважна роля, тъй като ООП е обектно-ориентиран език, който създава обектите на класовете. В OOP изучаваме класовете и обектите. Класовете съдържат членовете на данните, които са променливи от различни типове и различни членски функции. С помощта на инстанции имаме достъп до данните от всеки клас. Всеки клас има свой конструктор и деструктор, когато създавате класа. Конструкторът се извиква, когато се създава обектът от този клас. Можем също да инициализираме променливите на клас вътре в конструктора. Деструкторите също се създават автоматично с конструктора, но деструкторите унищожават обекта и това е последната функция, която се извиква преди унищожаването на обекта. Създава се името на класа, например клас „Професия“. Неговият конструктор е Profession(), а деструкторът е ~Profession (). Тримата носят едно име.

След като говорихме за ООП, конструктори и деструктори, нека сега да поговорим за виртуални деструктори. Виртуалните деструктори, както посочва името, унищожават обекта. Имаме базов клас и производен клас, който е извлечен от базовия клас. И двата класа имат своите конструктори и деструктори. Виртуалният деструктор освобождава реминисценцията, която се разпределя чрез обекта на производния клас, като същевременно изтрива обектите на производния клас, използвайки указател на базов клас с ключовата дума „виртуален“.

Защо използваме виртуалния деструктор?

Когато изпълнението на функциите на члена на класа приключи или изпълнението на метода main() е на път да приключи, деструкторът се извиква автоматично, за да освободи паметта, която е разпределена по време на създаването на обекта. Сега, защо използваме виртуален деструктор? Когато основният клас е изтрит, който сочи към производния клас, тук се използва указателят (*). Деструкторът на базовия клас се извиква само по време на този процес. Деструкторът на производния клас не се извиква, което води до проблеми. Един от тях е проблем с изтичане на памет. За да избегнем този проблем и да направим нашия код защитен, ние практически унищожаваме обектите, за да освободим пространството в паметта, което е било разпределено по време на създаването на обекти, като изтриваме деструктора на базовия клас.

Базов пример на C++ без виртуален деструктор

Нека да видим как функционира програмата без виртуален деструктор с проста програма, която изтрива показалеца.

Код:

#include

използване на пространство от имена std ;
клас Parent_Class0
{
публичен :
Родител_Клас0 ( )
{ cout << „Конструктор на родителски клас“ << endl ; }
~Родител_клас0 ( )
{ cout << „Деструктор на родителски клас“ << endl ; }
} ;
клас Дете_1 : публичен Parent_Class0
{
публичен :
Дете_1 ( )
{ cout << „Конструктор на детски класове“ << endl ; }
~Дете_1 ( )
{ cout << „Деструктор на детски класове“ << endl ; }
} ;
вътр основен ( )
{
Родител_Клас0 * показалец = ново дете_1 ( ) ;
изтриване на показалеца ;
връщане 0 ;
}

Този код обяснява как кодът се изпълнява без виртуален деструктор. Първо, създайте клас с име „Parent_Class0“, който ще бъде родителският клас. Вътре в този клас създайте конструктор и деструктор. Както знаем, конструкторът и деструкторът се наричат ​​по същия начин като класа. Деструкторът е представен подобно на конструктора, но има символ (~), който го отличава от конструктора. Вътре в конструктора и деструктора отпечатайте съобщение с помощта на “cout<<”. Сега създайте друг клас, който е „Child_1“. Този клас е извлечен от родителския клас, „Parent_Class0“. Произведеният клас има свой конструктор и деструктор, които съдържат съобщение за отпечатване на изходния екран.

В метода main() създаваме екземпляр на „Parent_Class0“ и му присвояваме производен клас. Решаващият момент, който трябва да запомните в този случай, е, че използваме указател за извличане на родителския клас. Когато влезе в родителския клас, той изпълнява конструктора на родителския клас. След това отива в дъщерния клас и изпълнява своя конструктор. Преди да изпълни деструктора на дъщерния клас, той трябва да изпълни деструктора на родителския клас. Компилаторът изпълнява деструктора на родителския клас и прекратява класа, без да изпълнява деструктора на дъщерен клас. Това е проблемът; не освобождава паметта на класа на детето. Той представлява конструктора на родителски клас, конструктора на дъщерен клас и деструктора на родителски клас. Това показва, че деструкторът на дъщерен клас не се изпълнява. След това изпълнение изтриваме указателя във функцията main().

Изход:

C++ пример с виртуален деструктор

Нека обсъдим виртуалния деструктор с прост код, за да разграничим как работи с и без виртуален деструктор.

Код:

#include

използване на пространство от имена std ;
клас Parent_Class0
{
публичен :
Родител_Клас0 ( )
{ cout << „Конструктор на родителски клас“ << endl ; }
виртуален ~Parent_Class0 ( )
{ cout << „Деструктор на родителски клас“ << endl ; }
} ;
клас Дете_1 : публичен Parent_Class0
{
публичен :
Дете_1 ( )
{ cout << „Конструктор на детски класове“ << endl ; }
виртуално ~Дете_1 ( )
{ cout << „Деструктор на детски класове“ << endl ; }
} ;
вътр основен ( )
{
Родител_Клас0 * показалец = ново дете_1 ( ) ;
изтриване на показалеца ;
връщане 0 ;
}

Първата програма обясни проблема, пред който сме изправени, без виртуален деструктор. Сега този код ще реши този проблем с помощта на виртуален деструктор. Първо, копирайте първия код и просто добавете една ключова дума на две места в тази програма. Тази дума е „виртуален“. Вмъкнете тази дума с деструктора на родителския клас, „Parent_Class0“. По същия начин споменете това с деструктора на дъщерния клас, който е „Child_1“, който е извлечен от родителския клас. Тази „виртуална“ ключова дума прави малка промяна и първо изпълнява деструктора на дъщерния клас „Child_1“. След това изпълнява деструктора на родителския клас, „Parent_Class0“. Останалата част от програмата работи по същия начин, както работи без виртуален деструктор. Като добавим това малко парче код, можем да спасим паметта си от изтичане. Сега той показва четири съобщения на конзолата. Първо, конструкторът на родителски клас, след това конструкторът на дъщерен клас, деструкторът на дъщерен клас и деструкторът на родителски клас. В крайна сметка изтриваме указателя в метода main().

Изход:

C++ пример за чист виртуален деструктор

В този код ще говорим за чистия виртуален деструктор, как работи и как се различава от виртуалния деструктор.

Код:

#include

клас Parent_0 {
публичен :
виртуален ~Родител_0 ( ) = 0 ;
} ;
Родител_0 :: ~Родител_0 ( )
{
std :: cout << „Здравей, аз съм Pure Destructor. Ти ми се обади!“ ;
}
клас Child_0 : публичен Parent_0 {
публичен :
~Дете_0 ( ) { std :: cout << „Производният деструктор е тук ' ; }
} ;

вътр основен ( )
{
Родител_0 * ptr_0 = ново дете_0 ( ) ;
изтрий ptr_0 ;
връщане 0 ;
}

Родителският клас „Parent_0“ се създава в първата стъпка на кода. Вътре в него създайте виртуалния родителски деструктор и му присвоете 0. Това настройва виртуалния деструктор на чист виртуален деструктор, което означава, че родителският клас вече е абстрактен и не можем да създадем екземплярите на този клас. Извън родителския клас „Parent_0“ дефинирайте деструкторите и std::cout. Необходимият текст се показва чрез използване на std::cout. След това извлечете клас „Child_0“ от родителския клас и дефинирайте неговия деструктор. Вътре в деструктора отпечатайте съобщение. Във функцията main() създайте указателя на родителския клас и му присвоете дъщерния клас.

Компилаторът отива към родителския клас „Parent_0“. Когато указателят е създаден, неговият конструктор се извиква автоматично. След това компилаторът отива в дъщерния клас, за да извика неговия конструктор. След успешното изпълнение на конструктора, той изпълнява деструктора на дъщерен клас “Child_0”. След това изпълнява деструктора на родителски клас. По този начин можем да направим чист виртуален деструктор. Не се насърчава използването му, защото чрез използването на този метод родителският клас става абстрактен, което го прави безполезен. Методологията, която се използва най-вече е виртуален деструктор и е добра практика.

Изход:

Заключение

Научихме за виртуалния деструктор, като започнем от концепцията за ООП и преминем към конструкторите и деструкторите. След като обяснихме всичко това, обсъдихме подробно виртуалния деструктор с примери за кодиране и чист виртуален деструктор. Преди да обясним виртуалния деструктор, трябва да знаем за конструкторите, деструкторите и наследяването. При наследяването ние наследяваме класовете от родителски клас. Дъщерните класове могат да бъдат повече от един, но родителският клас е само един. Виртуалните деструктори и чистите виртуални деструктори се прилагат при наследяване за спасяване от изтичане на памет. От основния пример до разширения пример, ние покрихме всичко, което трябва да знаете, за да започнете да използвате и практически да унищожите паметта на производния клас.