Πολλαπλή κληρονομικότητα στο C ++ και το πρόβλημα Diamond

Σε αντίθεση με πολλές άλλες αντικειμενοστρεφείς γλώσσες προγραμματισμού, το C ++ επιτρέπει πολλαπλή μεταβίβαση.

Η πολλαπλή κληρονομιά επιτρέπει σε μια παιδική τάξη να κληρονομήσει από περισσότερες από μία τάξεις γονέων.

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

Στα παρακάτω παραδείγματα, θα καλύψουμε μερικά σενάρια για τα οποία πρέπει να προσέξουμε.

Θα ξεκινήσουμε με ένα απλό παράδειγμα για να εξηγήσουμε αυτήν την ιδέα στο C ++.

Η έξοδος αυτού του κώδικα έχει ως εξής:

I'm breathing as a snake.I’m crawling as a snake.

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

Τώρα, θα προσθέσουμε λίγο πολυπλοκότητα.

Τι γίνεται αν η κλάση Reptile παρακάμπτει τη breathe()μέθοδο;

Η τάξη των φιδιών δεν θα ήξερε ποια breathe()μέθοδο να καλέσει. Αυτό είναι το «Διαμάντι Πρόβλημα».

Πρόβλημα με διαμάντια

Κοιτάξτε τον παρακάτω κώδικα. Είναι σαν τον κωδικό στο παραπάνω παράδειγμα, εκτός από το ότι έχουμε αντικαταστήσει τη breathe()μέθοδο στην κατηγορία Reptile .

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

member ‘breathe’ found in multiple base classes of different types

Το σφάλμα οφείλεται στο "Διαμάντι Πρόβλημα" πολλαπλής κληρονομιάς. Η τάξη των φιδιών δεν γνωρίζει ποια breathe()μέθοδος καλεί

Στο πρώτο παράδειγμα, μόνο η κατηγορία Ζώων είχε παρακάμψει τοbreathe()μέθοδος. Η τάξη ερπετών δεν είχε. Ως εκ τούτου, δεν ήταν πολύ δύσκολο για την τάξη του φιδιού να καταλάβει ποια breathe()μέθοδο να καλέσει. Και η τάξη των φιδιών κατέληξε να καλεί τη breathe()μέθοδο της τάξης των ζώων .

Στο δεύτερο παράδειγμα, η κατηγορία φιδιών κληρονομεί δύοbreathe() μεθόδους. Η breathe()μέθοδος της κατηγορίας ζώων και ερπετών . Δεδομένου ότι δεν έχουμε παρακάμψει τη breathe()μέθοδο στην κατηγορία Snake , υπάρχει αμφισημία.

Το C ++ έχει πολλά ισχυρά χαρακτηριστικά, όπως πολλαπλή κληρονομιά. Όμως, δεν είναι απαραίτητο να χρησιμοποιήσουμε όλες τις δυνατότητες που παρέχει.

Δεν προτιμώ τη χρήση πολλαπλής κληρονομιάς και τη χρήση εικονικής κληρονομιάς.

Η εικονική κληρονομιά λύνει το κλασικό "Diamond Problem". Διασφαλίζει ότι η παιδική τάξη λαμβάνει μόνο μία παρουσία της κοινής βασικής τάξης.

Με άλλα λόγια, η κατηγορία Snake θα έχει μόνο μία παρουσία της τάξης LivingThing . Οι τάξεις Animal και Reptile μοιράζονται αυτήν την παρουσία.

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

Ελπίζω να απολαύσατε αυτήν την επισκόπηση της πολλαπλής κληρονομιάς και του "Diamond Problem".