Virtuální destruktor v C++

Virtualni Destruktor V C



C++ je jazyk, který se používá jako základ v základní koncepci programování a posiluje logické myšlení programátorů. V C++ hraje OOP zásadní roli, protože OOP je objektově orientovaný jazyk, který vytváří objekty tříd. V OOP studujeme třídy a objekty. Třídy obsahují datové členy, které jsou proměnnými různých typů a různých členských funkcí. Pomocí instancí přistupujeme k datům jakékoli třídy. Každá třída má při vytváření třídy svůj konstruktor a destruktor. Konstruktor se nazývá sám, když je vytvořen objekt této třídy. Můžeme také inicializovat proměnné třídy uvnitř konstruktoru. Destruktory se také automaticky vytvářejí pomocí konstruktoru, ale destruktory ničí objekt a je to poslední funkce, která je volána před zničením objektu. Vytvoří se název třídy, například třída „Profese“. Jeho konstruktorem je Profession() a destruktorem je ~Profese (). Všichni tři se jmenují stejně.

Poté, co jsme mluvili o OOP, konstruktorech a destruktorech, pojďme nyní mluvit o virtuálních destruktorech. Virtuální destruktory, jak název specifikuje, zničí objekt. Máme základní třídu a odvozenou třídu, která je odvozena od základní třídy. Obě třídy mají své konstruktory a destruktory. Virtuální destruktor uvolňuje reminiscence, které jsou přidělovány prostřednictvím objektu odvozené třídy, zatímco maže objekty odvozené třídy pomocí ukazatele základní třídy s klíčovým slovem „virtual“.

Proč používáme virtuální destruktor?

Když je provádění funkcí členů třídy dokončeno nebo se provádění metody main() blíží ke konci, je automaticky zavolán destruktor, aby uvolnil paměť, která je přidělena během vytváření objektu. Proč tedy používáme virtuální destruktor? Když je odstraněna základní třída, která ukazuje na odvozenou třídu, použije se zde ukazatel (*). Destruktor základní třídy je volán pouze během tohoto procesu. Destruktor odvozené třídy není volán, což vede k problémům. Jedním z nich je problém s únikem paměti. Abychom se tomuto problému vyhnuli a náš kód byl zabezpečený, virtuálně zničíme objekty, abychom uvolnili paměťový prostor, který byl přidělen během vytváření objektů, odstraněním destruktoru základní třídy.

Základní příklad C++ bez virtuálního destruktoru

Podívejme se, jak program funguje bez virtuálního destruktoru s jednoduchým programem, který smaže ukazatel.

Kód:

#include

pomocí jmenného prostoru std ;
třída Parent_Class0
{
veřejnost :
Nadřazená_třída0 ( )
{ cout << 'Konstruktor rodičovské třídy' << endl ; }
~Rodičovská_třída0 ( )
{ cout << 'Destruktor rodičovské třídy' << endl ; }
} ;
třída Dítě_1 : public Parent_Class0
{
veřejnost :
Dítě_1 ( )
{ cout << 'Konstruktor dětské třídy' << endl ; }
~Child_1 ( )
{ cout << 'Destruktor dětské třídy' << endl ; }
} ;
int hlavní ( )
{
Nadřazená_třída0 * ukazatel = nové dítě_1 ( ) ;
odstranit ukazatel ;
vrátit se 0 ;
}

Tento kód vysvětluje, jak se kód spustí bez virtuálního destruktoru. Nejprve vytvořte třídu s názvem „Parent_Class0“, která bude rodičovskou třídou. Uvnitř této třídy vytvořte konstruktor a destruktor. Jak víme, konstruktor a destruktor se jmenují stejně jako třída. Destruktor je reprezentován podobně jako konstruktor, ale má symbol (~), který jej odlišuje od konstruktoru. Uvnitř konstruktoru a destruktoru vytiskněte zprávu pomocí „cout<<“. Nyní vytvořte další třídu, která je „Child_1“. Tato třída je odvozena od nadřazené třídy „Parent_Class0“. Odvozená třída má svůj konstruktor a destruktor, které obsahují zprávu k vytištění na výstupní obrazovce.

V metodě main() vytvoříme instanci „Parent_Class0“ a přiřadíme k ní odvozenou třídu. Rozhodujícím bodem, který je v tomto případě třeba pamatovat, je, že používáme ukazatel k načtení rodičovské třídy. Když jde do nadřazené třídy, spustí konstruktor nadřazené třídy. Poté přejde do podřízené třídy a provede její konstruktor. Před spuštěním destruktoru podřízené třídy musí provést destruktor nadřazené třídy. Kompilátor spustí destruktor nadřazené třídy a ukončí třídu, aniž by provedl destruktor podřízené třídy. To je ten problém; neuvolňuje paměť třídy dítěte. Představuje konstruktor nadřazené třídy, konstruktor podřízené třídy a destruktor nadřazené třídy. To ukazuje, že destruktor podřízené třídy není spuštěn. Po tomto provedení smažeme ukazatel ve funkci main().

Výstup:

Příklad C++ s virtuálním destruktorem

Pojďme diskutovat o virtuálním destruktoru pomocí jednoduchého kódu, abychom odlišili, jak funguje s virtuálním destruktorem a bez něj.

Kód:

#include

pomocí jmenného prostoru std ;
třída Parent_Class0
{
veřejnost :
Nadřazená_třída0 ( )
{ cout << 'Konstruktor rodičovské třídy' << endl ; }
virtuální ~Parent_Class0 ( )
{ cout << 'Destruktor rodičovské třídy' << endl ; }
} ;
třída Dítě_1 : public Parent_Class0
{
veřejnost :
Dítě_1 ( )
{ cout << 'Konstruktor dětské třídy' << endl ; }
virtuální ~Child_1 ( )
{ cout << 'Destruktor dětské třídy' << endl ; }
} ;
int hlavní ( )
{
Nadřazená_třída0 * ukazatel = nové dítě_1 ( ) ;
odstranit ukazatel ;
vrátit se 0 ;
}

První program vysvětlil problém, kterému čelíme bez virtuálního destruktoru. Nyní tento kód vyřeší tento problém pomocí virtuálního destruktoru. Nejprve zkopírujte první kód a přidejte jedno klíčové slovo na dvě místa v tomto programu. To slovo je „virtuální“. Vložte toto slovo s destruktorem nadřazené třídy „Parent_Class0“. Podobně to uveďte s destruktorem podřízené třídy, kterým je „Child_1“, který je odvozen od nadřazené třídy. Toto „virtuální“ klíčové slovo provede malou změnu a nejprve spustí destruktor podřízené třídy „Child_1“. Poté provede destruktor nadřazené třídy „Parent_Class0“. Zbytek programu funguje stejně jako bez virtuálního destruktoru. Přidáním tohoto malého kousku kódu můžeme zachránit naši paměť před únikem. Nyní na konzole zobrazí čtyři zprávy. Nejprve konstruktor nadřazené třídy, potom konstruktor podřízené třídy, destruktor podřízené třídy a destruktor nadřazené třídy. Nakonec smažeme ukazatel v rámci metody main().

Výstup:

Příklad C++ čistého virtuálního destruktoru

V tomto kódu budeme hovořit o čistém virtuálním destruktoru, jak funguje a jak se liší od virtuálního destruktoru.

Kód:

#include

třída Rodič_0 {
veřejnost :
virtuální ~Rodič_0 ( ) = 0 ;
} ;
Rodič_0 :: ~Rodič_0 ( )
{
std :: cout << 'Ahoj, jsem Pure Destructor. Volal jsi mě!' ;
}
třída Dítě_0 : veřejný rodič_0 {
veřejnost :
~Child_0 ( ) { std :: cout << „Odvozený destruktor je tady \n ' ; }
} ;

int hlavní ( )
{
Rodič_0 * ptr_0 = nové Dítě_0 ( ) ;
smazat ptr_0 ;
vrátit se 0 ;
}

Nadřazená třída „Parent_0“ je vytvořena v prvním kroku kódu. Uvnitř vytvořte virtuální nadřazený destruktor a přiřaďte mu 0. Tím se virtuální destruktor nastaví na čistě virtuální destruktor, což znamená, že nadřazená třída je nyní abstraktní a nemůžeme vytvářet instance této třídy. Mimo nadřazenou třídu „Parent_0“ definujte destruktory a std::cout. Požadovaný text se zobrazí pomocí std::cout. Poté z nadřazené třídy odvoďte třídu „Child_0“ a definujte její destruktor. Uvnitř destruktoru vytiskněte zprávu. Ve funkci main() vytvořte ukazatel nadřazené třídy a přiřaďte mu podřízenou třídu.

Kompilátor přejde do nadřazené třídy „Parent_0“. Když je ukazatel vytvořen, je automaticky volán jeho konstruktor. Poté kompilátor přejde do podřízené třídy, aby vyvolal její konstruktor. Po úspěšném provedení konstruktoru provede destruktor podřízené třídy „Child_0“. Poté provede destruktor nadřazené třídy. Tímto způsobem můžeme vytvořit čistý virtuální destruktor. Nedoporučuje se ji používat, protože použitím této metody se rodičovská třída stává abstraktní, což ji činí zbytečnou. Metoda, která se nejčastěji používá, je virtuální destruktor a je to dobrá praxe.

Výstup:

Závěr

Dozvěděli jsme se o virtuálním destruktoru počínaje konceptem OOP až po přechod ke konstruktorům a destruktorům. Po vysvětlení toho všeho jsme podrobně diskutovali o virtuálním destruktoru s příklady kódování a čistě virtuálním destruktorem. Než vysvětlíme virtuální destruktor, musíme vědět o konstruktorech, destruktorech a dědičnosti. Při dědění dědíme třídy z nadřazené třídy. Podřízených tříd může být více než jedna, ale rodičovská třída je pouze jedna. Virtuální destruktory a čistě virtuální destruktory se používají v dědičnosti, aby se zabránilo úniku paměti. Od základního příkladu po pokročilý příklad jsme probrali vše, co byste měli vědět, abyste mohli začít používat a virtuálně zničit paměť odvozené třídy.