| Both sides previous revision
Previous revision
Next revision
|
Previous revision
|
cpp:inheritance [2020/04/14 16:41] gthanos |
cpp:inheritance [2022/05/13 07:01] gthanos [Κληρονομικότητα] |
| Οι κλάσεις στη C++ μπορούν να επεκταθούν μέσω της κληρονομικότητας, δημιουργώντας νέες κλάσεις που διατηρούν τα χαρακτηριστικά των προγόνων τους. Η κληρονομικότητα προϋποθέτει ότι υπάρχει η βασική κλάση (πρόγονος) από την οποία προκύπτουν μία ή περισσότερες κλάσεις (απόγονοι). Οι απόγονοι διατηρούν τα χαρακτηριστικά του προγόνου, αλλά έχουν την δυνατότητα να προσθέσουν και επιπλέον χαρακτηριστικά στη νέα κλάση. | Οι κλάσεις στη C++ μπορούν να επεκταθούν μέσω της κληρονομικότητας, δημιουργώντας νέες κλάσεις που διατηρούν τα χαρακτηριστικά των προγόνων τους. Η κληρονομικότητα προϋποθέτει ότι υπάρχει η βασική κλάση (πρόγονος) από την οποία προκύπτουν μία ή περισσότερες κλάσεις (απόγονοι). Οι απόγονοι διατηρούν τα χαρακτηριστικά του προγόνου, αλλά έχουν την δυνατότητα να προσθέσουν και επιπλέον χαρακτηριστικά στη νέα κλάση. |
| |
| Στο παρακάτω παράδειγμα, από την κλάση //Shape// (διδιάστατο σχήμα) προκύπτει η κλάση //Rectangle// (ορθογώνιο παραλληλόγραμμο). Η κλάση //Shape// ορίζει την //private// μεταβλητή //color// που αφορά το χρώμα του τετραγώνου και το οποίο αποθηκεύεται σε μορφή [[wp>RGB]] και την //protected// μεταβλητή //borderWidth// που αφορά το πάχος του πλαισίου γύρο από το σχήμα. | Στο παρακάτω παράδειγμα, από την κλάση //Shape// (διδιάστατο σχήμα) προκύπτει η κλάση //Rectangle// (ορθογώνιο παραλληλόγραμμο). Η κλάση //Shape// ορίζει την //private// μεταβλητή //color// που αφορά το χρώμα του σχήματος, το οποίο αποθηκεύεται σε μορφή [[wp>RGB]] και την //protected// μεταβλητή //borderWidth// που αφορά το πάχος του πλαισίου γύρο από το σχήμα. |
| |
| <code cpp Shape.hpp> | <code cpp Shape.hpp> |
| |
| class Shape { | class Shape { |
| unsigned int color; | unsigned int color; |
| void setColor(unsigned char red, unsigned char blue, unsigned char green); | void setColor(unsigned char red, unsigned char blue, unsigned char green); |
| unsigned int getColor(); | unsigned int getColor(); |
| unsigned char getBorderWidth(); | |
| void setBorderWidth(unsigned char bw); | |
| unsigned int getArea(); | unsigned int getArea(); |
| }; | }; |
| <code cpp Shape.cpp> | <code cpp Shape.cpp> |
| #include <iostream> | #include <iostream> |
| #include <string> | |
| using namespace std; | using namespace std; |
| | |
| | #include "Shape.hpp" |
| |
| void Shape::setColor(unsigned int c) { color = c; } | void Shape::setColor(unsigned int c) { color = c; } |
| return 0; | return 0; |
| } | } |
| |
| unsigned char Shape::getBorderWidth() { return borderWidth; } | |
| void Shape::setBorderWidth(unsigned char bw) { borderWidth = bw; } | |
| |
| </code> | </code> |
| |
| <code cpp Rectangle.hpp> | <code cpp Rectangle.hpp> |
| |
| #include "Shape.hpp" | #include "Shape.hpp" |
| |
| unsigned int getHeight(); | unsigned int getHeight(); |
| unsigned int getArea(); | unsigned int getArea(); |
| | |
| | unsigned char getBorderWidth(); |
| | void setBorderWidth(unsigned char bw); |
| }; | }; |
| |
| </code> | </code> |
| |
| #include <iostream> | #include <iostream> |
| using namespace std; | using namespace std; |
| | |
| | #include "Rectangle.hpp" |
| |
| Rectangle::Rectangle(unsigned int c, unsigned char bw, unsigned int w, unsigned int h) : | Rectangle::Rectangle(unsigned int c, unsigned char bw, unsigned int w, unsigned int h) : |
| return Shape::getArea() + width * height; | return Shape::getArea() + width * height; |
| } | } |
| | |
| | unsigned char Rectangle::getBorderWidth() { return borderWidth; } |
| | void Rectangle::setBorderWidth(unsigned char bw) { borderWidth = bw; } |
| </code> | </code> |
| |
| <code cpp ShapeUsage.cpp> | <code cpp RectangleUsage.cpp> |
| #include "Rectangle.hpp" | #include "Rectangle.hpp" |
| | #include <iostream> |
| | using namespace std; |
| |
| int main() { | int main() { |
| Rectangle rectangle(0xffffff, 2, 10, 20); | Rectangle rectangle(0xffffff, 2, 10, 20); |
| | rectangle.setBorderWidth(8); |
| | |
| cout << "[Rectangle Properties] "; | cout << "[Rectangle Properties] "; |
| cout << " color: 0x" << hex << rectangle.getColor() << dec; | cout << " color: 0x" << std::hex << rectangle.getColor() << dec; |
| cout << " borderWidth: " << (int)rectangle.getBorderWidth(); | cout << " borderWidth: " << (int)rectangle.getBorderWidth(); |
| cout << " area: " << rectangle.getArea() << endl; | cout << " area: " << rectangle.getArea() << endl; |
| - Η απόγονος κλάση μπορεί να ορίσει επιπλέον πεδία και επιπλέον μεθόδους. Η απόγονος κλάση //Rectangle// ορίζει τα επιπλέον πεδία //width, height// και τις επιπλέον μεθόδους //getWidth//, //getHeight//, //setWidth//, //setHeight//. | - Η απόγονος κλάση μπορεί να ορίσει επιπλέον πεδία και επιπλέον μεθόδους. Η απόγονος κλάση //Rectangle// ορίζει τα επιπλέον πεδία //width, height// και τις επιπλέον μεθόδους //getWidth//, //getHeight//, //setWidth//, //setHeight//. |
| - Η απόγονος κλάση μπορεί να επαναορίσει μία μέθοδο η οποία είναι ήδη ορισμένη στη γονική κλάση. Η απόγονος κλάση //Rectangle// επαναορίζει τη μέθοδο //getArea//. | - Η απόγονος κλάση μπορεί να επαναορίσει μία μέθοδο η οποία είναι ήδη ορισμένη στη γονική κλάση. Η απόγονος κλάση //Rectangle// επαναορίζει τη μέθοδο //getArea//. |
| - Τα μέλη της γονικής κλάσης //Shape// που είναι δηλωμένα ως //protected// είναι προσβάσιμα από την απόγονο κλάση. Στο παραπάνω παράδειγμα η απόγονος κλάση //Rectangle// έχει πρόσβαση στο //protected// πεδίο //borderWidth// της γονικής κλάης. | - Τα μέλη της γονικής κλάσης //Shape// που είναι δηλωμένα ως //protected// είναι προσβάσιμα από την απόγονο κλάση. Στο παραπάνω παράδειγμα η απόγονος κλάση //Rectangle// έχει πρόσβαση στο //protected// πεδίο //borderWidth// της γονικής κλάσης. |
| - Τα μέλη της γονικής κλάσης //Shape// που είναι δηλωμένα ως //private// δεν είναι προσβάσιμα από την απόγονο κλάση //Rectangle//. | - Τα μέλη της γονικής κλάσης //Shape// που είναι δηλωμένα ως //private// δεν είναι προσβάσιμα από την απόγονο κλάση //Rectangle//. |
| - Όπως και στη Java, τα μέλη της γονικής κλάσης //Shape// ή της απογόνου κλάσης //Rectangle// που είναι δηλωμένα ως //public// είναι προσβάσιμα από οποιαδήποτε κλάση ή μέθοδο. Για παράδειγμα η //public// μεθόδος //getColor// της κλάσης //Shape// είναι προσβάσιμη από οποιοδήποτε κλάση ή μέθοδο (στο παράδειγμα από τη μέθοδο main). | - Όπως και στη Java, τα μέλη της γονικής κλάσης //Shape// ή της απογόνου κλάσης //Rectangle// που είναι δηλωμένα ως //public// είναι προσβάσιμα από οποιαδήποτε κλάση ή μέθοδο. Για παράδειγμα η //public// μεθόδος //getColor// της κλάσης //Shape// είναι προσβάσιμη από οποιοδήποτε κλάση ή μέθοδο (στο παράδειγμα από τη μέθοδο main). |
| ^ ^ μέλη της γονικής κλάσης ^^^ | ^ ^ μέλη της γονικής κλάσης ^^^ |
| ^ προσβασιμότητα ^ public ^ protected ^ private ^ | ^ προσβασιμότητα ^ public ^ protected ^ private ^ |
| | μέλη της ίδιας κλάσης | ναι | ναι | ναι | | | από μεθόδους της ίδιας κλάσης | ναι | ναι | ναι | |
| | μέλη υποκλάσης | ναι | ναι | όχι | | | από μεθόδους μίας υποκλάσης | ναι | ναι | όχι | |
| | μη μέλη της κλάσης | ναι | όχι | όχι | | | από μία άλλη κλάση χωρίς σχέση κληρονομικότητας | ναι | όχι | όχι | |
| |
| | ===== Κλήση μιας επανα-ορισμένης μεθόδου της γονικής κλάσης από την υποκλάση ===== |
| |
| <WRAP center round info 80%> | Όταν η απόγονος κλάση επαναορίζει μία μέθοδο με το ίδιο //signature// (ίδιο όνομα, ίδιος αριθμός και τύπος ορισμάτων) τότε συχνά θέλουμε να καλέσουμε τη μέθοδο της γονικής κλάσης στην απόγονο κλάση προκειμένου να την επεκτείνουμε. Ο τρόπος κλήσης της γονικής μεθόδου είναι βάζοντας ως πρόθεμα στο όνομα της μεθόδου το όνομα της γονικής κλάσης. Από το παραπάνω παράδειγμα, δείτε την υλοποίηση της συνάρτησης //getArea// στην κλάση //Rectangle// η οποία χρησιμοποιεί την συνάρτηση //getArea// της γονικής κλάσης //Shape//. |
| Όταν η απόγονος κλάση επαναορίζει μία μέθοδο με το ίδιο signature (ίδιο όνομα, ίδιος αριθμός και τύπος ορισμάτων) τότε συχνά θέλουμε να χρησιμοποιήσουμε τη γονική μέθοδο προκειμένου να την επεκτείνουμε. Ο τρόπος χρήσης της γονικής μεθόδου είναι βάζοντας ως πρόθεμα στη μέθοδο το όνομα της γονικής κλάσης. Από το παραπάνω παράδειγμα, δείτε την υλοποίηση της συνάρτησης //getArea// στην κλάση //Rectangle// η οποία χρησιμοποιεί την συνάρτηση //getArea// της γονικής κλάσης //Shape//. | |
| <code cpp> | <code cpp> |
| unsigned int Rectangle::getArea() { | unsigned int Rectangle::getArea() { |
| } | } |
| </code> | </code> |
| </WRAP> | |
| |
| |