Βίντεο: C++ μαθήματα (114) 2024
C ++ υποστηρίζει καθυστερημένη σύνδεση , η οποία είναι όταν επιλύει μια κλήση μεθόδου βάσει του χρόνου εκτέλεσης (ή δυναμικού τύπου) του αντικειμένου στόχου και όχι του δηλωμένου τύπου (ή του στατικού τύπου). Αυτό αποδεικνύεται στο ακόλουθο απόσπασμα κώδικα C ++:
#include using namespace std; Φούρνος κατηγορίας {public: virtual void cook () {cout << "μαγείρεμα με φούρνο" << endl;}}; class Φούρνος μικροκυμάτων: δημόσιος φούρνος {public: virtual void cook () {cout << "μαγείρεμα με φούρνο μικροκυμάτων" << endl;}}; άδειο prepareMeal (φούρνος και φούρνος) {φούρνος. cook ();}
Στη λειτουργία prepareMeal (), η κλήση στο φούρνο. cook () μπορεί να περάσει στο φούρνο:: cook () ή MicrowaveOven:: cook () ανάλογα με το χρόνο εκτέλεσης (ο "πραγματικός") τύπος του αντικειμένου του φούρνου που πέρασε.
Η εικονική λέξη κλειδί είναι κρίσιμη εδώ. Χωρίς αυτήν, η μέθοδος cook () θα δεσμευόταν νωρίτερα, με βάση τον τύπο χρόνου μεταγλώττισης και θα καλέσει τον φούρνο:: cook () κάθε φορά. Μόλις δηλωθεί εικονική στην κλάση Φούρνου, η μέθοδος θεωρείται ότι είναι εικονική σε κάθε υποκατηγορία, αλλά δεν βλάπτει να επαναλάβει τη δήλωση έτσι ώστε οι αναγνώστες να καταλάβουν.
Το ακόλουθο απλό πρόγραμμα επιδεικνύει αυτή την αρχή στην πράξη:
int main () {Φούρνος φούρνου. Παρασκευάστε το μέλι (φούρνος). Φούρνος μικροκυμάτων ΠαρασκευήMeal (mo); επιστροφή 0,}
Σε αυτό το πρόγραμμα, η κλήση για το μαγείρεμα () παράγει δύο διαφορετικές εξόδους ανάλογα με τον τύπο του φούρνου:
ότι μπορεί να οριστεί μια μέθοδος στην κατηγορία βάσης. Εξετάστε προσεκτικά την περίπτωση του φούρνου. Υπάρχουν διάφοροι τύποι φούρνων - συμβατικοί φούρνοι, φούρνοι μεταφοράς και φούρνοι μικροκυμάτων - αλλά θα μπορούσαμε να υποστηρίξουμε ότι δεν υπάρχει πραγματικός φούρνος που δεν ανήκει σε μία από αυτές τις υποκατηγορίες. Μπορεί να είστε σε θέση να πείτε πώς οι διάφοροι τύποι φούρνων εκτελούν τη λειτουργία μαγειρέματος - δηλαδή, τι μπορεί να καθορίσει ένα συμβατικόOven:: cook () και ένα μικροκυμαινόμενο:: cook (). Δεν είναι πιθανόν να ορίσετε ποιες ενέργειες πρέπει να εκτελέσει ο φούρνος:: cook ().
να δηλώσετε μια μέθοδο αλλά αφήστε την μη υλοποιημένη εάν δεν υπάρχει εφαρμογή. Κάποιος χρησιμοποιεί την ακόλουθη περίεργη σύνταξη για να το κάνει: Φούρνος κατηγορίας {public: virtual void cook () = 0;};
Αυτός ο κώδικας δηλώνει μια μέθοδο Φούρνος:: cook () που δεσμεύεται αργά αλλά δεν εφαρμόζει τη μέθοδο. Στην πραγματικότητα, προχωρεί περαιτέρω λέγοντας ότι η μέθοδος δεν θα εφαρμοστεί. Στην C ++, μια τέτοια μέθοδος λέγεται ότι είναι
καθαρή εικονική . Οι προγραμματιστές C ++ χρησιμοποιούν επίσης τον όρο που προτιμάται σε πολλές άλλες έντονα πληκτρολογούμενες γλώσσες υπολογιστών: abstract .Η κλάση του φούρνου λέγεται ότι είναι αφηρημένη. Μια περίληψη αντιπροσωπεύει μια ιδιότητα που γνωρίζετε ότι διαθέτει η τάξη, αλλά δεν γνωρίζει πώς να εφαρμόσει ξεκάθαρα στην τρέχουσα τάξη.
Μια κλάση είναι αφηρημένη εάν περιέχει μία ή περισσότερες καθαρές εικονικές μεθόδους. Η σημασία αυτού είναι ότι δεν μπορείτε να δημιουργήσετε μια αφηρημένη κλάση. Επομένως, δεν επιτρέπονται πλέον τα εξής:
int main () {Φούρνος φούρνου. Παρασκευάστε το μέλι (φούρνος). επιστροφή 0?}
Ο λόγος για αυτό είναι πολύ απλός: εάν δημιουργήσατε ένα αντικείμενο του φούρνου κατηγορίας και στη συνέχεια προσπαθήσατε να επικαλεστείτε φούρνο. cook (), τι πρέπει να κάνει ο μεταγλωττιστής;
Σε ένα πιο φιλοσοφικό επίπεδο, είναι ωραίο να πούμε ότι υπάρχει ένας κοινός όρος που ονομάζεται Φούρνος που περιγράφει τους συμβατικούς φούρνους και τους φούρνους μικροκυμάτων και τους φούρνους μεταφοράς. Αυτός ο όρος Φούρνος είναι μια συνηθισμένη έννοια επειδή δεσμεύει τις ομοιότητες σε όλες αυτές τις υποκατηγορίες. Αλλά δεν υπάρχει περίπτωση ενός φούρνου που δεν είναι μία από τις υποκατηγορίες του φούρνου.
Μια υποκλάση μιας αφηρημένης κλάσης είναι αφηρημένη, μέχρις ότου όλες οι καθαρές εικονικές μέθοδοι έχουν αντικατασταθεί από μη αφηρημένες (δηλαδή
συγκεκριμένες ) εκδόσεις. Έτσι, η κλάση Μικροκυμάτων στο προηγούμενο απόσπασμα κώδικα δεν είναι αφηρημένη - ακόμα κι αν ο Φούρνος ήταν αφηρημένος - επειδή αγνοεί το cook () με τη δική του συγκεκριμένη έκδοση. Παρατηρήστε ότι δεν υπάρχει τίποτα λάθος με τη συνάρτηση prepareMeal () που ορίζεται ως εξής:
void prepareMeal (φούρνος και φούρνος) {φούρνος. cook ();}
Παρόλο που το όρισμα δηλώνεται ως φούρνος, μπορεί να χρησιμοποιηθεί μόνο με κάποια υποκατηγορία του φούρνου, όπως είναι το MicrowaveOven ή το ConventionalOven, για το οποίο ορίζεται ο cook ().