This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
cpp:inheritance [2017/04/22 09:51] gthanos [Άλλες μορφές κληρονομικότητας] |
cpp:inheritance [2022/05/13 07:01] (current) gthanos [Κληρονομικότητα] |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Κληρονομικότητα ====== | ====== Κληρονομικότητα ====== | ||
| - | ====== Κληρονομικότητα | + | Οι κλάσεις στη C++ μπορούν να επεκταθούν μέσω της κληρονομικότητας, δημιουργώντας νέες κλάσεις που διατηρούν τα χαρακτηριστικά των προγόνων τους. Η κληρονομικότητα προϋποθέτει ότι υπάρχει η βασική κλάση (πρόγονος) από την οποία προκύπτουν μία ή περισσότερες κλάσεις (απόγονοι). Οι απόγονοι διατηρούν τα χαρακτηριστικά του προγόνου, |
| - | Σε αναλογία με τη Java, οι κλάσεις στη C++ μπορούν να επεκταθούν μέσω | + | Στο παρακάτω παράδειγμα, από |
| - | Στο παρακάτω παράδειγμα, | + | <code cpp Shape.hpp> |
| - | + | class Shape { | |
| - | <code cpp Rectangle.cpp> | + | |
| - | #include < | + | |
| - | using namespace std; | + | |
| - | + | ||
| - | class Rectangle | + | |
| - | private: | + | |
| - | int width; | + | |
| protected: | protected: | ||
| - | | + | |
| public: | public: | ||
| - | | + | |
| - | | + | |
| - | void setWidth(int w); | + | void setColor(unsigned |
| - | void setHeight(int h); | + | void setColor(unsigned char red, unsigned char blue, unsigned char green); |
| - | int getWidth(); | + | |
| - | int getHeight(); | + | |
| }; | }; | ||
| - | |||
| - | Rectangle:: | ||
| - | width = w; height = h; | ||
| - | } | ||
| - | |||
| - | bool Rectangle:: | ||
| - | if(r.width == width && r.height == height) | ||
| - | return true; | ||
| - | return false; | ||
| - | } | ||
| - | |||
| - | void Rectangle:: | ||
| - | void Rectangle:: | ||
| - | int Rectangle:: | ||
| - | int Rectangle:: | ||
| </ | </ | ||
| - | <code cpp Square.cpp> | + | <code cpp Shape.cpp> |
| - | # | + | # |
| + | using namespace std; | ||
| - | class Square: public Rectangle { | + | #include " |
| - | int color; | + | |
| - | | + | |
| - | | + | |
| - | bool equals(Square &s); | + | |
| - | void setColor(int c); | + | |
| - | void setColor(unsigned char r, unsigned char b, unsigned char g); | + | |
| - | int getColor(); | + | |
| - | int getArea(); | + | |
| - | }; | + | |
| - | Square:: | + | void Shape::setColor(unsigned |
| - | void Square:: | + | void Shape:: |
| - | void Square:: | + | |
| color = red; | color = red; | ||
| color <<= 8; | color <<= 8; | ||
| Line 65: | Line 35: | ||
| } | } | ||
| - | int Square:: | + | unsigned |
| return color; | return color; | ||
| } | } | ||
| - | int Square::getArea() { | + | Shape::Shape(unsigned int c, unsigned char bw) : color(c), borderWidth(bw) { |
| - | // height is accessible from Square | + | |
| - | // since it is a protected member. | + | |
| - | return getWidth() * height; | + | |
| } | } | ||
| - | bool Square::equals(Square &s) { | + | Shape::Shape(unsigned char red, unsigned char blue, unsigned char green, unsigned char bw) : borderWidth(bw) { |
| - | if( Rectangle:: | + | |
| - | | + | |
| - | | + | |
| } | } | ||
| - | </ | ||
| - | <code cpp SquareUsage.cpp> | + | unsigned |
| - | #include " | + | |
| - | + | ||
| - | int main() { | + | |
| - | Square square(5); | + | |
| - | cout << " | + | |
| - | cout << " | + | |
| return 0; | return 0; | ||
| } | } | ||
| </ | </ | ||
| - | Από τα παραπάνω παρατηρούμε τα εξής: | + | <code cpp Rectangle.hpp> |
| - | - Η κληρονομικότητα δηλώνεται μέσω της δήλωσης '' | + | #include "Shape.hpp" |
| - | - Τα μέλη της γονικής κλάσης // | + | |
| - | - Όπως και στη Java, τα μέλη της γονικής κλάσης // | + | |
| - | Συνοπτικά ο πίνακας προσβασιμότητας παρατίθεται παρακάτω: | + | class Rectangle |
| - | ^ ^ μέλη της γονικής κλάσης | + | |
| - | ^ προσβασιμότητα | + | unsigned int width, height; |
| - | | μέλη της ίδιας κλάσης | + | public: |
| - | | μέλη υποκλάσης | + | |
| - | | μη μέλη της κλάσης | + | void setWidth(unsigned int w); |
| + | void setHeight(unsigned int h); | ||
| + | unsigned int getWidth(); | ||
| + | unsigned int getHeight(); | ||
| + | unsigned int getArea(); | ||
| + | |||
| + | unsigned char getBorderWidth(); | ||
| + | void setBorderWidth(unsigned char bw); | ||
| + | }; | ||
| + | </ | ||
| - | <WRAP center round info 80%> | + | <code cpp Rectangle.cpp> |
| - | Όταν μία κλάση έχει πρόσβαση σε ένα πεδίο, το πεδίο αυτό δεν είναι προσβάσιμο μόνο για το τρέχον αντικείμενο, | + | # |
| - | </WRAP> | + | using namespace std; |
| - | <WRAP center round info 80%> | + | #include "Rectangle.hpp" |
| - | Όταν η απόγονος κλάση επαναορίζει μία μέθοδο με το ίδιο signature (ίδιο όνομα, ίδιος αριθμός και τύπος ορισμάτων) τότε συχνά θέλουμε να χρησιμοποιήσουμε τη γονική μέθοδο προκειμένου να την επεκτείνουμε. Ο τρόπος χρήσης της γονικής μεθόδου είναι βάζοντας ως πρόθεμα στη μέθοδο το όνομα της γονικής κλάσης. Ο λόγος που δεν υπάρχει κάποια δεσμευμένη λέξη (όπως ο τελεστής //super// στη Java) που να αναφέρεται στη γονική κλάση είναι η πολλαπλή κληρονομικότητα που επιτρέπει η C++. Από το παραπάνω παράδειγμα, | + | |
| - | <code cpp> | + | |
| - | bool Square:: | + | |
| - | if( Rectangle::equals(s) && s.color == color) | + | |
| - | return true; | + | |
| - | return false; | + | |
| - | } | + | |
| - | </ | + | |
| - | </ | + | |
| - | ===== Άλλες μορφές κληρονομικότητας ===== | + | Rectangle:: |
| + | Shape(c, bw) , width(w), height(h) { } | ||
| - | Εκτός από την κληρονομικότητα τύπου //public// ('' | + | void Rectangle:: |
| - | ^ | + | void Rectangle:: |
| - | ^ μέλη της γονικής κλάσης | + | unsigned int Rectangle:: |
| - | | public μέλη | + | unsigned int Rectangle:: |
| - | | protected μέλη | + | |
| - | | private μέλη | + | |
| - | Δείτε το παρακάτω παράδειγμα που παραθέτει αναλυτικά τα επίπεδα της προσβασιμότητας | + | unsigned int Rectangle:: |
| + | /* this is how you call a function | ||
| + | * from the parent class. | ||
| + | */ | ||
| + | int area = Shape:: | ||
| + | return Shape:: | ||
| + | } | ||
| - | <code cpp> | + | unsigned char Rectangle::getBorderWidth() { return borderWidth; } |
| - | class Parent { | + | void Rectangle:: |
| - | public: | + | </ |
| - | int publicMember; | + | |
| - | protected: | + | |
| - | int protectedMember; | + | |
| - | private: | + | |
| - | int privateMember; | + | |
| - | }; | + | |
| - | class ChildA : public Parent { | + | <code cpp RectangleUsage.cpp> |
| - | // publicMember is public | + | #include " |
| - | // protectedMember is protected | + | #include < |
| - | // privateMember is not accessible from ChildA | + | using namespace std; |
| - | }; | + | |
| - | class ChildB : protected Parent | + | int main() |
| - | // publicMember is protected | + | |
| - | // protectedMember is protected | + | |
| - | // privateMember is not accessible from ChildB | + | |
| - | }; | + | cout << " |
| - | + | cout << " color: 0x" << std::hex << rectangle.getColor() << dec; | |
| - | class ChildC | + | cout << " borderWidth: |
| - | // publicMember is private | + | |
| - | // protectedMember is private | + | |
| - | // privateMember is not accessible from ChildC | + | |
| - | }; | + | } |
| </ | </ | ||
| - | Στο παραπάνω παράδειγμα συμπερασματικά | + | Από |
| - | * Για την κλάση //ChildA// (//public// κληρονομικότητα) | + | - Η κληρονομικότητα |
| - | | + | - Η απόγονος |
| - | | + | - Η απόγονος |
| + | | ||
| + | - Τα μέλη | ||
| + | | ||
| - | <WRAP center round tip 80%> | + | Συνοπτικά ο πίνακας προσβασιμότητας παρατίθεται |
| - | Η κληρονομικότητα τύπου //private// ή // | + | ^ ^ μέλη της γονικής κλάσης |
| - | </ | + | ^ |
| + | | από μεθόδους της ίδιας κλάσης | ναι | ||
| + | | από | ||
| + | | από μία άλλη κλάση χωρίς σχέση κληρονομικότητας | ||
| + | ===== Κλήση μιας επανα-ορισμένης μεθόδου της γονικής κλάσης από την υποκλάση ===== | ||
| + | Όταν η απόγονος κλάση επαναορίζει μία μέθοδο με το ίδιο // | ||
| + | <code cpp> | ||
| + | unsigned int Rectangle:: | ||
| + | return Shape:: | ||
| + | } | ||
| + | </ | ||