User Tools

Site Tools


cpp:polymorphism

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
cpp:polymorphism [2017/04/25 12:55] gthanoscpp:polymorphism [Unknown date] (current) – external edit (Unknown date) 127.0.0.1
Line 1: Line 1:
 ====== Δυναμικός Πολυμορφισμός ====== ====== Δυναμικός Πολυμορφισμός ======
  
-Ας επανέλθουμε στο αρχικό παράδειγμα της κληρονομικότητας και ας ορίσουμε δύο νέες μεταβλητές α) μία μεταβλητή τύπου δείκτη και μία μεταβλητή τύπου αναφορά σε ένα αντικείμενο τύπου //Shape2D// ως εξής:+Ας επανέλθουμε στο αρχικό παράδειγμα της κληρονομικότητας και ας ορίσουμε δύο νέες μεταβλητές α) μία μεταβλητή τύπου δείκτη και μία μεταβλητή τύπου αναφορά σε ένα αντικείμενο τύπου //Shape// ως εξής:
  
 <code cpp ShapeUsage.cpp> <code cpp ShapeUsage.cpp>
Line 7: Line 7:
  
 int main() { int main() {
-  Shape2D shape(0x333333, 5); +  Shape shape(0x333333, 5); 
-  Shape2D &shape_ref = shape, *shape_ptr = &shape;+  Shape &shape_ref = shape, *shape_ptr = &shape;
   Rectangle rectangle(0xffffff, 2, 10, 20);   Rectangle rectangle(0xffffff, 2, 10, 20);
-  Shape2D &rect_ref = rectangle, *rect_ptr = &rectangle;+  Shape &rect_ref = rectangle, *rect_ptr = &rectangle;
  
-  cout << "Shape2D area: " << shape.getArea() << endl; +  cout << "Shape area: " << shape.getArea() << endl; 
-  cout << "Shape2D reference area: " << shape_ref.getArea() << endl; +  cout << "Shape reference area: " << shape_ref.getArea() << endl; 
-  cout << "Shape2D pointer area: " << shape_ptr->getArea() << endl;+  cout << "Shape pointer area: " << shape_ptr->getArea() << endl;
   cout << endl;   cout << endl;
   cout << "Rectangle area: " << rectangle.getArea() << endl;   cout << "Rectangle area: " << rectangle.getArea() << endl;
Line 24: Line 24:
 Μεταγλωττίζοντας και εκτελώντας τον παραπάνω κώδικα λαμβάνουμε τα εξής: Μεταγλωττίζοντας και εκτελώντας τον παραπάνω κώδικα λαμβάνουμε τα εξής:
 <code> <code>
-Shape2D area: 0 +Shape area: 0 
-Shape2D reference area: 0 +Shape reference area: 0 
-Shape2D pointer area: 0+Shape pointer area: 0
  
 Rectangle area: 200 Rectangle area: 200
Line 35: Line 35:
 Από τα παραπάνω συμπεραίνουμε ότι η επιλογή κλήσης της μεθόδου //getArea// δεν γίνεται δυναμικά με βάση τον τύπο του αντικειμένου στον οποίο δείχνει ο δείκτης ή η αναφορά, αλλά στατικά με βάση τον τύπο δεδομένων για τον οποίο δηλώνεται ο δείκτης ή η αναφορά. Σε αυτή την περίπτωση η επιλογή της μεθόδου γίνεται από τον //compiler// κατά τη μεταγλώττιση του προγράμματος. Από τα παραπάνω συμπεραίνουμε ότι η επιλογή κλήσης της μεθόδου //getArea// δεν γίνεται δυναμικά με βάση τον τύπο του αντικειμένου στον οποίο δείχνει ο δείκτης ή η αναφορά, αλλά στατικά με βάση τον τύπο δεδομένων για τον οποίο δηλώνεται ο δείκτης ή η αναφορά. Σε αυτή την περίπτωση η επιλογή της μεθόδου γίνεται από τον //compiler// κατά τη μεταγλώττιση του προγράμματος.
  
-Εάν θέλουμε η επιλογή της μεθόδου να γίνεται δυναμικά με βάση τον τύπο του αντικειμένου που δείχνει ο δείκτης ή η αναφορά θα πρέπει να δηλώσουμε τη μέθοδο //getArea// στη γονική κλάση //Shape2D// ως //**virtual**// όπως παρακάτω:+Εάν θέλουμε η επιλογή της μεθόδου να γίνεται δυναμικά με βάση τον τύπο του αντικειμένου που δείχνει ο δείκτης ή η αναφορά θα πρέπει να δηλώσουμε τη μέθοδο //getArea// στη γονική κλάση //Shape// ως //**virtual**// όπως παρακάτω:
 <code cpp> <code cpp>
-class Shape2D {+class Shape {
   public:   public:
     virtual unsigned int getArea();     virtual unsigned int getArea();
-+}; 
-unsigned int Shape2D::getArea() { return 0; }+unsigned int Shape::getArea() { return 0; }
 </code> </code>
  
 Με αυτό τον τρόπο δηλώνουμε προς τον //compiler// ότι η απόφαση για τον ποια μέθοδος θα κληθεί δεν θα ληφθεί κατά τη μεταγλώττιση, αλλά κατά την εκτέλεση του προγράμματος. Δηλώνοντας τη μέθοδο //getArea// ως //**virtual**// στη γονική κλάση το αποτέλεσμα της εκτέλεσης είναι το εξής: Με αυτό τον τρόπο δηλώνουμε προς τον //compiler// ότι η απόφαση για τον ποια μέθοδος θα κληθεί δεν θα ληφθεί κατά τη μεταγλώττιση, αλλά κατά την εκτέλεση του προγράμματος. Δηλώνοντας τη μέθοδο //getArea// ως //**virtual**// στη γονική κλάση το αποτέλεσμα της εκτέλεσης είναι το εξής:
 <code> <code>
-Shape2D area: 0 +Shape area: 0 
-Shape2D reference area: 0 +Shape reference area: 0 
-Shape2D pointer area: 0+Shape pointer area: 0
  
 Rectangle area: 200 Rectangle area: 200
Line 55: Line 55:
 </code> </code>
  
-====== Pure Virtual συναρτήσεις και abstract κλάσεις ======+====== Pure virtual συναρτήσεις και abstract κλάσεις ======
  
 Εκτός από τις //virtual// μεθόδους που είδαμε προηγούμενα μπορούμε να έχουμε και //pure virtual// μεθόδους. Οι μέθοδοι που χαρακτηρίζονται //pure virtual// όταν ορίζονται σε μία κλάση, δηλώνεται μόνο το //prototype// τους, χωρίς να δηλώνεται σώμα και ακολουθεί η δήλωση ''=0''. Εκτός από τις //virtual// μεθόδους που είδαμε προηγούμενα μπορούμε να έχουμε και //pure virtual// μεθόδους. Οι μέθοδοι που χαρακτηρίζονται //pure virtual// όταν ορίζονται σε μία κλάση, δηλώνεται μόνο το //prototype// τους, χωρίς να δηλώνεται σώμα και ακολουθεί η δήλωση ''=0''.
Line 64: Line 64:
 Η κλάση που περιέχει μία ή περισσότερες //pure virtual// συναρτήσεις είναι //abstract// και δεν μπορεί να παράγει αντικείμενα, **ακόμη και εάν διαθέτει κατασκευαστή**. Μόνο οι κλάσεις που θα κληρονομήσουν τη συγκεκριμένη κλάση και θα παρέχουν υλοποιήσεις όλων των //pure virtual// μεθόδων θα μπορέσουν να παράγουν αντικείμενα. Η κλάση που περιέχει μία ή περισσότερες //pure virtual// συναρτήσεις είναι //abstract// και δεν μπορεί να παράγει αντικείμενα, **ακόμη και εάν διαθέτει κατασκευαστή**. Μόνο οι κλάσεις που θα κληρονομήσουν τη συγκεκριμένη κλάση και θα παρέχουν υλοποιήσεις όλων των //pure virtual// μεθόδων θα μπορέσουν να παράγουν αντικείμενα.
  
-Για παράδειγμα, στην κλάση //Shape2D// είναι λογικό να δηλώσουμε την μέθοδο //getArea// ως //pure virtual// (αντί να επιστρέφει μηδέν) μιας και η συγκεκριμένη συνάρτηση δεν έχει νόημα για το κλάση //Shape2D//, αλλά μόνο για τις υποκλάσεις αυτής. Η κλάση //Shape2D// διαμορφώνεται ως εξής:+Για παράδειγμα, στην κλάση //Shape// είναι λογικό να δηλώσουμε την μέθοδο //getArea// ως //pure virtual// (αντί να επιστρέφει μηδέν) μιας και η συγκεκριμένη συνάρτηση δεν έχει νόημα για το κλάση //Shape//, αλλά μόνο για τις υποκλάσεις αυτής. Η κλάση //Shape// διαμορφώνεται ως εξής:
  
 <code cpp Shape.cpp> <code cpp Shape.cpp>
Line 74: Line 74:
 #define __SHAPE2D__ #define __SHAPE2D__
  
-class Shape2D {+class Shape {
     unsigned int color;     unsigned int color;
   protected:   protected:
     unsigned char borderWidth;     unsigned char borderWidth;
   public:   public:
-    Shape2D(unsigned int c, unsigned char bw); +    Shape(unsigned int c, unsigned char bw); 
-    Shape2D(unsigned char red, unsigned char blue, unsigned char green, unsigned char bw);+    Shape(unsigned char red, unsigned char blue, unsigned char green, unsigned char bw);
     void setColor(unsigned int c);     void setColor(unsigned int c);
     void setColor(unsigned char red, unsigned char blue, unsigned char green);     void setColor(unsigned char red, unsigned char blue, unsigned char green);
Line 89: Line 89:
 }; };
  
-void Shape2D::setColor(unsigned int c) { color = c; } +void Shape::setColor(unsigned int c) { color = c; } 
-void Shape2D::setColor(unsigned char red, unsigned char blue, unsigned char green) {+void Shape::setColor(unsigned char red, unsigned char blue, unsigned char green) {
   color = red;   color = red;
   color <<= 8;   color <<= 8;
Line 98: Line 98:
 } }
  
-unsigned int Shape2D::getColor() { return color; } +unsigned int Shape::getColor() { return color; } 
-Shape2D::Shape2D(unsigned int c, unsigned char bw) : color(c), borderWidth(bw) {} +Shape::Shape(unsigned int c, unsigned char bw) : color(c), borderWidth(bw) {} 
-Shape2D::Shape2D(unsigned char red, unsigned char blue, unsigned char green, unsigned char bw) : borderWidth(bw) { setColor(red, blue, green); } +Shape::Shape(unsigned char red, unsigned char blue, unsigned char green, unsigned char bw) : borderWidth(bw) { setColor(red, blue, green); } 
-unsigned char Shape2D::getBorderWidth() { return borderWidth;+unsigned char Shape::getBorderWidth() { return borderWidth;
-void Shape2D::setBorderWidth(unsigned char bw) { borderWidth = bw; }+void Shape::setBorderWidth(unsigned char bw) { borderWidth = bw; }
 #endif #endif
 </code> </code>
Line 113: Line 113:
 </code> </code>
  
-Επειδή η κλάση //Shape2D// είναι πλέον //abstract// δεν μπορεί να δώσει αντικείμενα. Έτσι η συνάρτηση //main// διαμορφώνεται ως εξής.+Επειδή η κλάση //Shape// είναι πλέον //abstract// δεν μπορεί να δώσει αντικείμενα. Έτσι η συνάρτηση //main// διαμορφώνεται ως εξής.
 <code cpp ShapeUsage.cpp> <code cpp ShapeUsage.cpp>
 #include "Rectangle.cpp" #include "Rectangle.cpp"
Line 119: Line 119:
 int main() { int main() {
   Rectangle rectangle(0xffffff, 2, 10, 20);   Rectangle rectangle(0xffffff, 2, 10, 20);
-  Shape2D &rect_ref = rectangle, *rect_ptr = &rectangle;+  Shape &rect_ref = rectangle, *rect_ptr = &rectangle;
  
   cout << "Rectangle area: " << rectangle.getArea() << endl;   cout << "Rectangle area: " << rectangle.getArea() << endl;
cpp/polymorphism.1493124912.txt.gz · Last modified: 2017/04/25 11:55 (external edit)