Virtual Destructor σε C++

Virtual Destructor Se C



Η C++ είναι η γλώσσα που χρησιμοποιείται για να δώσει μια βάση στη βασική έννοια του προγραμματισμού και κάνει δυνατή τη λογική σκέψη των προγραμματιστών. Στην C++, η OOP παίζει ζωτικό ρόλο, καθώς η OOP είναι μια αντικειμενοστρεφής γλώσσα που δημιουργεί τα αντικείμενα των κλάσεων. Στο OOP, μελετάμε τις κλάσεις και τα αντικείμενα. Οι κλάσεις περιέχουν τα μέλη δεδομένων που είναι μεταβλητές διαφορετικών τύπων και διαφορετικές συναρτήσεις μέλους. Με τη βοήθεια περιπτώσεων, έχουμε πρόσβαση στα δεδομένα οποιασδήποτε κλάσης. Κάθε τάξη έχει τον κατασκευαστή και τον καταστροφέα της όταν δημιουργείτε την κλάση. Ο κατασκευαστής καλείται ο εαυτός του όταν δημιουργείται το αντικείμενο αυτής της κλάσης. Μπορούμε επίσης να αρχικοποιήσουμε τις μεταβλητές μιας κλάσης μέσα στον κατασκευαστή. Οι καταστροφείς δημιουργούνται επίσης αυτόματα με τον κατασκευαστή, αλλά οι καταστροφείς καταστρέφουν το αντικείμενο και είναι η τελευταία συνάρτηση που καλείται πριν την καταστροφή του αντικειμένου. Δημιουργείται το όνομα της τάξης, για παράδειγμα η κλάση «Επάγγελμα». Ο κατασκευαστής του είναι Profession() και ο καταστροφέας είναι ~Profession (). Οι τρεις τους έχουν το ίδιο όνομα.

Αφού μιλήσουμε για το OOP, τους κατασκευαστές και τους καταστροφείς, ας μιλήσουμε τώρα για εικονικούς καταστροφείς. Οι εικονικοί καταστροφείς, όπως ορίζει το όνομα, καταστρέφουν το αντικείμενο. Έχουμε μια βασική κλάση και μια παράγωγη κλάση που προέρχεται από τη βασική κλάση. Και οι δύο τάξεις έχουν τους κατασκευαστές και τους καταστροφείς τους. Ο εικονικός καταστροφέας απελευθερώνει την ανάμνηση που κατανέμεται μέσω του παραγόμενου αντικειμένου κλάσης, ενώ διαγράφει τα αντικείμενα της παραγόμενης κλάσης χρησιμοποιώντας έναν δείκτη κλάσης βάσης με την «εικονική» λέξη-κλειδί.

Γιατί χρησιμοποιούμε τον εικονικό καταστροφέα;

Όταν ολοκληρωθεί η εκτέλεση των συναρτήσεων μέλους κλάσης ή η εκτέλεση της μεθόδου main() πρόκειται να τελειώσει, ο καταστροφέας καλείται αυτόματα να ελευθερώσει τη μνήμη που εκχωρείται κατά τη δημιουργία του αντικειμένου. Τώρα, γιατί χρησιμοποιούμε έναν εικονικό καταστροφέα; Όταν διαγράφεται η βασική κλάση που οδηγεί στην παράγωγη κλάση, ο δείκτης (*) χρησιμοποιείται εδώ. Ο καταστροφέας κλάσης βάσης καλείται μόνο κατά τη διάρκεια αυτής της διαδικασίας. Δεν καλείται ο παραγόμενος καταστροφέας κλάσης που οδηγεί σε προβλήματα. Ένα από αυτά είναι ένα ζήτημα διαρροής μνήμης. Για να αποφύγουμε αυτό το ζήτημα και να κάνουμε τον κώδικά μας ασφαλή, καταστρέφουμε ουσιαστικά τα αντικείμενα για να ελευθερώσουμε τον χώρο μνήμης που είχε εκχωρηθεί κατά τη δημιουργία αντικειμένων διαγράφοντας τον καταστροφέα κλάσης βάσης.

Βασικό παράδειγμα C++ χωρίς Virtual Destructor

Ας δούμε πώς λειτουργεί το πρόγραμμα χωρίς εικονικό καταστροφέα με ένα απλό πρόγραμμα που διαγράφει τον δείκτη.

Κώδικας:

#include

χρησιμοποιώντας το namespace std ;
τάξη Parent_Class0
{
δημόσιο :
Parent_Class0 ( )
{ cout << 'Κατασκευαστής Τάξης Γονέων' << endl ; }
~Parent_Class0 ( )
{ cout << 'Γονικός καταστροφέας τάξης' << endl ; }
} ;
τάξη Παιδί_1 : δημόσιο Parent_Class0
{
δημόσιο :
Παιδί_1 ( )
{ cout << «Κατασκευαστής Παιδικής Τάξης» << endl ; }
~Παιδί_1 ( )
{ cout << 'Καταστροφέας Παιδικής Τάξης' << endl ; }
} ;
ενθ κύριος ( )
{
Parent_Class0 * δείκτης = νέο παιδί_1 ( ) ;
διαγραφή δείκτη ;
ΕΠΙΣΤΡΟΦΗ 0 ;
}

Αυτός ο κώδικας εξηγεί πώς εκτελείται ο κώδικας χωρίς εικονικό καταστροφέα. Πρώτα απ 'όλα, δημιουργήστε μια τάξη με το όνομα 'Parent_Class0' που θα είναι η γονική κλάση. Μέσα σε αυτήν την κλάση, δημιουργήστε έναν κατασκευαστή και έναν καταστροφέα. Όπως γνωρίζουμε, ο κατασκευαστής και ο καταστροφέας ονομάζονται το ίδιο με την κλάση. Ο καταστροφέας αναπαρίσταται παρόμοια με τον κατασκευαστή, αλλά έχει ένα σύμβολο (~) που τον διαφοροποιεί από τον κατασκευαστή. Μέσα στον κατασκευαστή και τον καταστροφέα, εκτυπώστε ένα μήνυμα χρησιμοποιώντας 'cout<<'. Τώρα, δημιουργήστε μια άλλη κλάση που είναι 'Child_1'. Αυτή η κλάση προέρχεται από τη γονική κλάση, 'Parent_Class0'. Η παραγόμενη κλάση έχει τον κατασκευαστή και τον καταστροφέα της που περιέχουν ένα μήνυμα για εκτύπωση στην οθόνη εξόδου.

Στη μέθοδο main(), δημιουργούμε μια παρουσία της 'Parent_Class0' και της εκχωρούμε μια παραγόμενη κλάση. Το κρίσιμο σημείο που πρέπει να θυμόμαστε σε αυτήν την περίπτωση είναι ότι χρησιμοποιούμε έναν δείκτη για να ανακτήσουμε τη γονική κλάση. Όταν μπαίνει μέσα στη γονική κλάση, εκτελεί τον κατασκευαστή γονικής κλάσης. Στη συνέχεια, πηγαίνει στην κλάση παιδί και εκτελεί τον κατασκευαστή του. Πριν εκτελέσει τον καταστροφέα της θυγατρικής κλάσης, πρέπει να εκτελέσει τον καταστροφέα της γονικής κλάσης. Ο μεταγλωττιστής εκτελεί τον καταστροφέα της γονικής κλάσης και τερματίζει την κλάση χωρίς να εκτελέσει τον καταστροφέα μιας θυγατρικής κλάσης. Αυτό είναι το πρόβλημα; δεν ελευθερώνει τη μνήμη της τάξης του παιδιού. Αντιπροσωπεύει τον κατασκευαστή μιας γονικής κλάσης, τον κατασκευαστή μιας θυγατρικής κλάσης και τον καταστροφέα μιας γονικής κλάσης. Αυτό δείχνει ότι ο καταστροφέας μιας παιδικής τάξης δεν εκτελείται. Μετά από αυτήν την εκτέλεση, διαγράφουμε τον δείκτη στη συνάρτηση main().

Παραγωγή:

Παράδειγμα C++ με Virtual Destructor

Ας συζητήσουμε τον εικονικό καταστροφέα με έναν απλό κώδικα για να διαφοροποιήσουμε πώς λειτουργεί με και χωρίς εικονικό καταστροφέα.

Κώδικας:

#include

χρησιμοποιώντας το namespace std ;
τάξη Parent_Class0
{
δημόσιο :
Parent_Class0 ( )
{ cout << 'Κατασκευαστής Τάξης Γονέων' << endl ; }
εικονική ~Parent_Class0 ( )
{ cout << 'Γονικός καταστροφέας τάξης' << endl ; }
} ;
τάξη Παιδί_1 : δημόσιο Parent_Class0
{
δημόσιο :
Παιδί_1 ( )
{ cout << «Κατασκευαστής Παιδικής Τάξης» << endl ; }
εικονικό ~Child_1 ( )
{ cout << 'Καταστροφέας Παιδικής Τάξης' << endl ; }
} ;
ενθ κύριος ( )
{
Parent_Class0 * δείκτης = νέο παιδί_1 ( ) ;
διαγραφή δείκτη ;
ΕΠΙΣΤΡΟΦΗ 0 ;
}

Το πρώτο πρόγραμμα εξήγησε το πρόβλημα που αντιμετωπίζουμε χωρίς εικονικό καταστροφέα. Τώρα, αυτός ο κώδικας θα λύσει αυτό το πρόβλημα χρησιμοποιώντας έναν εικονικό καταστροφέα. Αρχικά, αντιγράψτε τον πρώτο κώδικα και απλώς προσθέστε μία λέξη-κλειδί σε δύο σημεία σε αυτό το πρόγραμμα. Αυτή η λέξη είναι «εικονική». Εισαγάγετε αυτήν τη λέξη με τον καταστροφέα της γονικής κλάσης, 'Parent_Class0'. Ομοίως, αναφέρετε αυτό με τον καταστροφέα της τάξης παιδιού που είναι 'Child_1' που προέρχεται από τη γονική τάξη. Αυτή η 'εικονική' λέξη-κλειδί κάνει μια μικρή αλλαγή και εκτελεί πρώτα τον καταστροφέα της θυγατρικής τάξης 'Child_1'. Στη συνέχεια, εκτελεί τον καταστροφέα της γονικής κλάσης, 'Parent_Class0'. Το υπόλοιπο πρόγραμμα λειτουργεί όπως λειτουργεί χωρίς εικονικό καταστροφέα. Προσθέτοντας αυτό το μικρό κομμάτι κώδικα, μπορούμε να σώσουμε τη μνήμη μας από διαρροή. Τώρα, εμφανίζει τέσσερα μηνύματα στην κονσόλα. Πρώτα, ο κατασκευαστής μιας γονικής κλάσης, μετά ο κατασκευαστής μιας θυγατρικής κλάσης, ο καταστροφέας μιας θυγατρικής κλάσης και ο καταστροφέας μιας γονικής κλάσης. Στο τέλος, διαγράφουμε τον δείκτη μέσα στη μέθοδο main().

Παραγωγή:

C++ Παράδειγμα Pure Virtual Destructor

Σε αυτόν τον κώδικα, θα μιλήσουμε για τον καθαρό εικονικό καταστροφέα, πώς λειτουργεί και πώς διαφέρει από έναν εικονικό καταστροφέα.

Κώδικας:

#include

τάξη Γονέας_0 {
δημόσιο :
εικονικό ~Parent_0 ( ) = 0 ;
} ;
Γονέας_0 :: ~Γονέας_0 ( )
{
std :: cout << 'Γεια, είμαι ο Pure Destructor. Με κάλεσες!' ;
}
τάξη Παιδί_0 : δημόσιος Γονέας_0 {
δημόσιο :
~Παιδί_0 ( ) { std :: cout << «Ο παράγωγος καταστροφέας είναι εδώ \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 μέχρι να προχωρήσουμε προς τους κατασκευαστές και τους καταστροφείς. Αφού εξηγήσαμε όλα αυτά, συζητήσαμε λεπτομερώς για τον εικονικό καταστροφέα με παραδείγματα κωδικοποίησης και καθαρό εικονικό καταστροφέα. Πριν εξηγήσουμε τον εικονικό καταστροφέα, πρέπει να γνωρίζουμε για τους κατασκευαστές, τους καταστροφείς και την κληρονομικότητα. Στην κληρονομικότητα, κληρονομούμε τις κλάσεις από μια γονική κλάση. Οι θυγατρικές τάξεις μπορεί να είναι περισσότερες από μία, αλλά η γονική τάξη είναι μόνο μία. Οι εικονικοί καταστροφείς και οι καθαροί εικονικοί καταστροφείς εφαρμόζονται κληρονομικά για εξοικονόμηση από τη διαρροή μνήμης. Από το βασικό παράδειγμα έως το προηγμένο παράδειγμα, καλύψαμε όλα όσα πρέπει να γνωρίζετε για να ξεκινήσετε να χρησιμοποιείτε και να καταστρέψετε ουσιαστικά τη μνήμη της παραγόμενης κλάσης.