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

Έχω μια καλή κατανόηση των περισσότερων θεωριών OO, αλλά το μόνο πράγμα που με μπερδεύει πολύ είναι οι εικονικοί καταστροφείς.

Νόμιζα ότι ο καταστροφέας καλείται πάντα, ό,τι και να γίνει και για κάθε αντικείμενο στην αλυσίδα.

Πότε πρέπει να τους κάνετε εικονικούς και γιατί;

Λύση

Οι εικονικοί καταστροφείς είναι χρήσιμοι όταν ενδέχεται να διαγράψετε μια περίπτωση μιας παράγωγης κλάσης μέσω ενός δείκτη προς τη βασική κλάση:

class Base 
{
    // some virtual methods
};

class Derived : public Base
{
    ~Derived()
    {
        // Do some important cleanup
    }
};

Εδώ, θα παρατηρήσετε ότι δεν δήλωσα ότι ο καταστροφέας της Base's είναι "εικονικός". Τώρα, ας ρίξουμε μια ματιά στο παρακάτω απόσπασμα:

Base *b = new Derived();
// use b
delete b; // Here's the problem!

Αφού ο καταστροφέας της Base's δεν είναι virtual και το b είναι ένα Base* που δείχνει σε ένα Derived αντικείμενο, το delete b έχει απροσδιόριστη συμπεριφορά:

[Στην delete b], εάν ο στατικός τύπος του αντικειμένου που πρόκειται να διαγραφεί είναι διαφορετικός από τον δυναμικό τύπο του, ο στατικός τύπος πρέπει να είναι μια βασική κλάση του δυναμικού τύπου του αντικειμένου που πρόκειται να διαγραφεί. διαγραφεί και ο στατικός τύπος πρέπει να έχει εικονικό καταστροφέα ή το συμπεριφορά είναι απροσδιόριστη.

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

Συνοψίζοντας, πάντα να κάνετε τους καταστροφείς των βασικών κλάσεων virtual όταν προορίζονται για πολυμορφικό χειρισμό.

Αν θέλετε να αποτρέψετε τη διαγραφή μιας περίπτωσης μέσω ενός δείκτη βασικής κλάσης, μπορείτε να κάνετε τον καταστροφέα της βασικής κλάσης προστατευμένο και μη εικονικό- με αυτόν τον τρόπο, ο μεταγλωττιστής δεν θα σας αφήσει να καλέσετε το delete σε έναν δείκτη βασικής κλάσης.

Μπορείτε να μάθετε περισσότερα για την εικονικότητα και τον εικονικό καταστροφέα κλάσης βάσης στο αυτό το άρθρο από τον Herb Sutter.

Σχόλια (10)

Δήλωση εικονικών καταστροφέων σε πολυμορφικές βασικές κλάσεις. Αυτό είναι το σημείο 7 στο Αποτελεσματική C++ του Scott Meyers. Ο Meyers συνεχίζει να συνοψίζει ότι αν μια κλάση έχει οποιαδήποτε εικονική συνάρτηση, θα πρέπει να έχει έναν εικονικό καταστροφέα και ότι οι κλάσεις που δεν έχουν σχεδιαστεί για να είναι κλάσεις βάσης ή που δεν έχουν σχεδιαστεί για να χρησιμοποιηθούν πολυμορφικά δεν θα πρέπει να δηλώνουν εικονικούς καταστροφείς.

Σχόλια (7)

Κάντε τον καταστροφέα εικονικό όποτε η κλάση σας είναι πολυμορφική.

Σχόλια (0)