cpp:polymorphism

Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
cpp:polymorphism [2017/04/25 09:43]
gthanos
cpp:polymorphism [2017/05/11 09:13]
gthanos [Δυναμικός Πολυμορφισμός]
Line 7: Line 7:
  
 int main() { int main() {
 +  Shape2D shape(0x333333, 5);
 +  Shape2D &shape_ref = shape, *shape_ptr = &shape;
   Rectangle rectangle(0xffffff, 2, 10, 20);   Rectangle rectangle(0xffffff, 2, 10, 20);
-  Shape2D &ref = rectangle, *ptr = &rectangle;+  Shape2D &rect_ref = rectangle, *rect_ptr = &rectangle;
  
 +  cout << "Shape2D area: " << shape.getArea() << endl;
 +  cout << "Shape2D reference area: " << shape_ref.getArea() << endl;
 +  cout << "Shape2D pointer area: " << shape_ptr->getArea() << endl;
 +  cout << endl;
   cout << "Rectangle area: " << rectangle.getArea() << endl;   cout << "Rectangle area: " << rectangle.getArea() << endl;
-  cout << "Reference area: " << ref.getArea() << endl; +  cout << "Rectangle reference area: " << rect_ref.getArea() << endl; 
-  cout << "Pointer area: " << ptr->getArea() << endl;   +  cout << "Rectangle pointer area: " << rect_ptr->getArea() << endl; 
-   +
-  return 0+
-}+
 </code> </code>
  
 Μεταγλωττίζοντας και εκτελώντας τον παραπάνω κώδικα λαμβάνουμε τα εξής: Μεταγλωττίζοντας και εκτελώντας τον παραπάνω κώδικα λαμβάνουμε τα εξής:
 <code> <code>
 +Shape2D area: 0
 +Shape2D reference area: 0
 +Shape2D pointer area: 0
 +
 Rectangle area: 200 Rectangle area: 200
-Reference area: 0 +Rectangle reference area: 0 
-Pointer area: 0+Rectangle pointer area: 0
 </code> </code>
  
Line 29: Line 37:
 Εάν θέλουμε η επιλογή της μεθόδου να γίνεται δυναμικά με βάση τον τύπο του αντικειμένου που δείχνει ο δείκτης ή η αναφορά θα πρέπει να δηλώσουμε τη μέθοδο //getArea// στη γονική κλάση //Shape2D// ως //**virtual**// όπως παρακάτω: Εάν θέλουμε η επιλογή της μεθόδου να γίνεται δυναμικά με βάση τον τύπο του αντικειμένου που δείχνει ο δείκτης ή η αναφορά θα πρέπει να δηλώσουμε τη μέθοδο //getArea// στη γονική κλάση //Shape2D// ως //**virtual**// όπως παρακάτω:
 <code cpp> <code cpp>
-<class Shape2D {+class Shape2D {
   public:   public:
     virtual unsigned int getArea();     virtual unsigned int getArea();
-}+};
 unsigned int Shape2D::getArea() { return 0; } unsigned int Shape2D::getArea() { return 0; }
 </code> </code>
  
-Με αυτό τον τρόπο δηλώνουμε προς τον //compiler// ότι η απόφαση για τον ποιά μέθοδος θα κληθεί δεν θα ληφθεί κατά τη μεταγλώττιση, αλλά κατά την εκτέλεση του προγράμματος. Δηλώνοντας τη μέθοδο //getArea// ως //**virtual**// στη γονική κλάση το αποτέλεσμα της εκτέλεσης είναι το εξής:+Με αυτό τον τρόπο δηλώνουμε προς τον //compiler// ότι η απόφαση για τον ποια μέθοδος θα κληθεί δεν θα ληφθεί κατά τη μεταγλώττιση, αλλά κατά την εκτέλεση του προγράμματος. Δηλώνοντας τη μέθοδο //getArea// ως //**virtual**// στη γονική κλάση το αποτέλεσμα της εκτέλεσης είναι το εξής:
 <code> <code>
 +Shape2D area: 0
 +Shape2D reference area: 0
 +Shape2D pointer area: 0
 +
 Rectangle area: 200 Rectangle area: 200
-Reference area: 200 +Rectangle reference area: 200 
-Pointer area: 200+Rectangle pointer area: 200 
 +</code> 
 + 
 +====== Pure virtual συναρτήσεις και abstract κλάσεις ====== 
 + 
 +Εκτός από τις //virtual// μεθόδους που είδαμε προηγούμενα μπορούμε να έχουμε και //pure virtual// μεθόδους. Οι μέθοδοι που χαρακτηρίζονται //pure virtual// όταν ορίζονται σε μία κλάση, δηλώνεται μόνο το //prototype// τους, χωρίς να δηλώνεται σώμα και ακολουθεί η δήλωση ''=0''
 +<code cpp> 
 +virtual <return type> <function_name>(<function parameters) =0; 
 +</code> 
 + 
 +Η κλάση που περιέχει μία ή περισσότερες //pure virtual// συναρτήσεις είναι //abstract// και δεν μπορεί να παράγει αντικείμενα, **ακόμη και εάν διαθέτει κατασκευαστή**. Μόνο οι κλάσεις που θα κληρονομήσουν τη συγκεκριμένη κλάση και θα παρέχουν υλοποιήσεις όλων των //pure virtual// μεθόδων θα μπορέσουν να παράγουν αντικείμενα. 
 + 
 +Για παράδειγμα, στην κλάση //Shape2D// είναι λογικό να δηλώσουμε την μέθοδο //getArea// ως //pure virtual// (αντί να επιστρέφει μηδέν) μιας και η συγκεκριμένη συνάρτηση δεν έχει νόημα για το κλάση //Shape2D//, αλλά μόνο για τις υποκλάσεις αυτής. Η κλάση //Shape2D// διαμορφώνεται ως εξής: 
 + 
 +<code cpp Shape.cpp> 
 +#include <iostream> 
 +#include <string> 
 +using namespace std; 
 + 
 +#ifndef __SHAPE2D__ 
 +#define __SHAPE2D__ 
 + 
 +class Shape2D { 
 +    unsigned int color; 
 +  protected: 
 +    unsigned char borderWidth; 
 +  public: 
 +    Shape2D(unsigned int c, unsigned char bw); 
 +    Shape2D(unsigned char red, unsigned char blue, unsigned char green, unsigned char bw); 
 +    void setColor(unsigned int c); 
 +    void setColor(unsigned char red, unsigned char blue, unsigned char green); 
 +    unsigned int getColor(); 
 +    unsigned char getBorderWidth(); 
 +    void setBorderWidth(unsigned char bw); 
 +    virtual unsigned int getArea() = 0; 
 +}; 
 + 
 +void Shape2D::setColor(unsigned int c) { color = c; } 
 +void Shape2D::setColor(unsigned char red, unsigned char blue, unsigned char green) { 
 +  color = red; 
 +  color <<= 8; 
 +  color |= blue; 
 +  color <<= 8; 
 +  color |= green; 
 +
 + 
 +unsigned int Shape2D::getColor() { return color; } 
 +Shape2D::Shape2D(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); } 
 +unsigned char Shape2D::getBorderWidth() { return borderWidth;
 +void Shape2D::setBorderWidth(unsigned char bw) { borderWidth = bw; } 
 +#endif 
 +</code> 
 + 
 +Αντίστοιχα, η μέθοδος getArea() της κλάσης //Rectangle// διαμορφώνεται ως εξής: 
 +<code cpp> 
 +unsigned int Rectangle::getArea() { 
 +  return width * height; 
 +
 +</code> 
 + 
 +Επειδή η κλάση //Shape2D// είναι πλέον //abstract// δεν μπορεί να δώσει αντικείμενα. Έτσι η συνάρτηση //main// διαμορφώνεται ως εξής. 
 +<code cpp ShapeUsage.cpp> 
 +#include "Rectangle.cpp" 
 + 
 +int main() { 
 +  Rectangle rectangle(0xffffff, 2, 10, 20); 
 +  Shape2D &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> </code>
  
  
cpp/polymorphism.txt · Last modified: 2020/04/15 08:48 (external edit)