This is an old revision of the document!
Κληρονομικότητα
Σε αναλογία με τη Java, οι κλάσεις στη C++ μπορούν να επεκταθούν μέσω της κληρονομικότητας, δημιουργώντας νέες κλάσεις που διατηρούν τα χαρακτηριστικά των προγόνων τους. Η κληρονομικότητα προϋποθέτει ότι υπάρχει η βασική κλάση (πρόγονος) από την οποία προκύπτουν μία ή περισσότερες κλάσεις (απόγονοι). Οι απόγονοι διατηρούν τα χαρακτηριστικά του προγόνου, αλλά έχουν την δυνατότητα να προσθέσουν και επιπλέον χαρακτηριστικά στη νέα κλάση.
Στο παρακάτω παράδειγμα, από την κλάση Rectangle (ορθογώνιο παραλλολόγραμμο) προκύπτει η κλάση Square (τετράγωνο). Η κλάση Square εκτός των διαστάσεων του τετραγώνου ορίζει μία επιπλέον παράμετρο color που αφορά το χρώμα του τετραγώνου και το οποίο αποθηκεύεται σε μορφή RGB.
- Rectangle.cpp
#include <iostream> using namespace std; class Rectangle { private: int width; protected: int height; public: Rectangle(int w, int h); bool equals(Rectangle &r); void setWidth(int w); void setHeight(int h); int getWidth(); int getHeight(); }; Rectangle::Rectangle(int w, int h) { width = w; height = h; } bool Rectangle::equals(Rectangle &r) { if(r.width == width && r.height == height) return true; return false; } void Rectangle::setWidth(int w) { width = w; } void Rectangle::setHeight(int h) { height = h; } int Rectangle::getWidth() { return width; } int Rectangle::getHeight() { return height; }
- Square.cpp
#include "Rectangle.cpp" class Square: public Rectangle { int color; public: Square(int s); bool equals(Square &s); void setColor(int c); void setColor(unsigned char r, unsigned char b, unsigned char g); int getColor(); int getArea(); }; Square::Square(int s) : Rectangle(s,s) {} void Square::setColor(int c) { color = c; } void Square::setColor(unsigned char red, unsigned char blue, unsigned char green) { color = red; color <<= 8; color |= blue; color <<= 8; color |= green; } int Square::getColor() { return color; } int Square::getArea() { // height is accessible from Square // since it is a protected member. return getWidth() * height; cout << "Square area.\n"; } bool Square::equals(Square &s) { if( Rectangle::equals(s) && s.color == color) return true; return false; }
- SquareUsage.cpp
#include "Square.cpp" int main() { Square square(5); cout << "Square dimensions: [" << square.getWidth() <<"," << square.getHeight() << "]\n"; cout << "Square area: " << square.getArea() << endl; return 0; }
Από τα παραπάνω παρατηρούμε τα εξής:
- Η κληρονομικότητα δηλώνεται μέσω της δήλωσης
class derived_class_name : public base_class_name { };
(στο παραπάνω παράδειγμαclass Square: public Rectangle { };
). - Τα μέλη της γονικής κλάσης Rectangle που είναι δηλωμένα ως protected είναι προσβάσιμα από την απόγονο κλάση Square. Τα μέλη της γονικής κλάσης Rectangle που είναι δηλωμένα ως private δεν είναι προσβάσιμα από την απόγονο κλάση Square.
- Όπως και στη Java, τα μέλη της γονικής κλάσης Rectangle ή της απογόνου κλάσης Square που είναι δηλωμένα ως public είναι προσβάσιμα από οποιαδήποτε κλάση ή μέθοδο.
Συνοπτικά ο πίνακας προσβασιμότητας παρατίθεται παρακάτω:
μέλη της γονικής κλάσης | |||
---|---|---|---|
προσβασιμότητα | public | protected | private |
μέλη της ίδιας κλάσης | ναι | ναι | ναι |
μέλη υποκλάσης | ναι | ναι | όχι |
μη μέλη της κλάσης | ναι | όχι | όχι |
Όταν μία κλάση έχει πρόσβαση σε ένα πεδίο, το πεδίο αυτό δεν είναι προσβάσιμο μόνο για το τρέχον αντικείμενο, αλλά και για όλα αντικείμενα του τύπου της κλάσης. Στο παραπάνω παράδειγμα, η μέθοδος equals στις κλάσεις Rectangle και Square έχει πρόσβαση στα πεδία του αντικειμένου της μεθόδου που λαμβάνεται ως όρισμα.
Όταν η απόγονος κλάση επαναορίζει μία μέθοδο με το ίδιο signature (ίδιο όνομα, ίδιος αριθμός και τύπος ορισμάτων) τότε συχνά θέλουμε να χρησιμοποιήσουμε τη γονική μέθοδο προκειμένου να την επεκτείνουμε. Ο τρόπος χρήσης της γονικής μεθόδου είναι βάζοντας ως πρόθεμα στη μέθοδο το όνομα της γονικής κλάσης. Ο λόγος που δεν υπάρχει κάποια δεσμευμένη λέξη (όπως ο τελεστής super στη Java) που να αναφέρεται στη γονική κλάση είναι η πολλαπλή κληρονομικότητα που επιτρέπει η C++. Από το παραπάνω παράδειγμα, δείτε την υλοποίηση της equals στην κλάση Square.
bool Square::equals(Square &s) { if( Rectangle::equals(s) && s.color == color) return true; return false; }