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:40] 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>
 #include "Rectangle.cpp" #include "Rectangle.cpp"
-#include "Triangle.cpp" 
  
 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 25: 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 36: 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 56: 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 62: Line 61:
 virtual <return type> <function_name>(<function parameters) =0; virtual <return type> <function_name>(<function parameters) =0;
 </code> </code>
-Για παράδειγμα, στην κλάση //Shape2D// είναι λογικό να δηλώσουμε την μέθοδο //getArea// ως //pure virtual// (αντί να επιστρέφει μηδέν) μιας και η συγκεκριμένη συνάρτηση δεν έχει νόημα για το κλάση //Shape2D//, αλλά μόνο για τις υποκλάσεις αυτής. Η κλάση //Shape2D// διαμορφώνεται ως εξής:+ 
 +Η κλάση που περιέχει μία ή περισσότερες //pure virtual// συναρτήσεις είναι //abstract// και δεν μπορεί να παράγει αντικείμενα, **ακόμη και εάν διαθέτει κατασκευαστή**. Μόνο οι κλάσεις που θα κληρονομήσουν τη συγκεκριμένη κλάση και θα παρέχουν υλοποιήσεις όλων των //pure virtual// μεθόδων θα μπορέσουν να παράγουν αντικείμενα. 
 + 
 +Για παράδειγμα, στην κλάση //Shape// είναι λογικό να δηλώσουμε την μέθοδο //getArea// ως //pure virtual// (αντί να επιστρέφει μηδέν) μιας και η συγκεκριμένη συνάρτηση δεν έχει νόημα για το κλάση //Shape//, αλλά μόνο για τις υποκλάσεις αυτής. Η κλάση //Shape// διαμορφώνεται ως εξής:
  
 <code cpp Shape.cpp> <code cpp Shape.cpp>
Line 72: 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 87: 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 96: Line 98:
 } }
  
-unsigned int Shape2D::getColor() { +unsigned int Shape::getColor() { return color; } 
-  return color; +Shape::Shape(unsigned int c, unsigned char bw) : color(c), borderWidth(bw) {} 
-}+Shape::Shape(unsigned char red, unsigned char blue, unsigned char green, unsigned char bw) : borderWidth(bw) { setColor(red, blue, green); } 
 +unsigned char Shape::getBorderWidth() { return borderWidth;
 +void Shape::setBorderWidth(unsigned char bw) { borderWidth = bw; } 
 +#endif 
 +</code>
  
-Shape2D::Shape2D(unsigned int c, unsigned char bw) : color(c), borderWidth(bw) {} +Αντίστοιχα, η μέθοδος getArea() της κλάσης //Rectangle// διαμορφώνεται ως εξής
-Shape2D::Shape2D(unsigned char red, unsigned char blue, unsigned char green, unsigned char bw) : borderWidth(bw) { +<code cpp> 
-  setColor(red, blue, green);+unsigned int Rectangle::getArea() { 
 +  return width * height;
 } }
 +</code>
  
-unsigned char Shape2D::getBorderWidth() { return borderWidth; } +Επειδή η κλάση //Shape// είναι πλέον //abstract// δεν μπορεί να δώσει αντικείμενα. Έτσι η συνάρτηση //main// διαμορφώνεται ως εξής. 
-void Shape2D::setBorderWidth(unsigned char bw) { borderWidth = bw; }+<code cpp ShapeUsage.cpp> 
 +#include "Rectangle.cpp"
  
-#endif +int main() { 
-</code>+  Rectangle rectangle(0xffffff, 2, 10, 20); 
 +  Shape &rect_ref = rectangle, *rect_ptr = &rectangle;
  
 +  cout << "Rectangle area: " << rectangle.getArea() << endl;
 +  cout << "Rectangle reference area: " << rect_ref.getArea() << endl;
 +  cout << "Rectangle pointer area: " << rect_ptr->getArea() << endl;
 +
 +</code>
  
  
cpp/polymorphism.1493124042.txt.gz · Last modified: 2017/04/25 11:40 (external edit)