cpp:const_member_functions

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:const_member_functions [2017/05/15 07:18]
gthanos
cpp:const_member_functions [2019/03/07 05:42]
gthanos [Υπερφόρτωση const και non-const συναρτήσεων]
Line 1: Line 1:
 ====== Const μέθοδοι της κλάσης ====== ====== Const μέθοδοι της κλάσης ======
  
-Όταν δηλώνεται ένα αντικείμενο ως //const// (όπως παρακάτω), τότε οι μεταβλητές του αντικειμένου μπορούν μόνο να διαβαστούν αλλά όχι να μεταβληθούν, πρόκειται δηλαδή για ένα αμετάβλητο αντικείμενο. Εξαίρεση αποτελεί ο κατασκευαστής του αντικειμένου, ο οποίος αρχικοποιεί κανονικά το αντικείμενο και μεταβάλλει τις τιμές των μεταβλητών του. +Όταν δηλώνεται ένα αντικείμενο ως //const// (όπως παρακάτω), τότε τα πεδία του αντικειμένου μπορούν μόνο να διαβαστούν αλλά όχι να μεταβληθούν, πρόκειται δηλαδή για ένα αμετάβλητο αντικείμενο. Εξαίρεση αποτελεί ο κατασκευαστής του αντικειμένου, ο οποίος αρχικοποιεί κανονικά το αντικείμενο και μεταβάλλει τις μεταβλητές του.
- +
-<code cpp Point.cpp> +
-#include <iostream> +
-using namespace std; +
- +
-class Point { +
-    int x, y; +
-  public: +
-    Point(int vx,int vy) { x = vx; y = vy; }    +
-    void setX(int vx) { x = vx; } +
-    void setY(int vy) { y = vy; } +
-    int getX() { return x; } +
-    int getY() { return y; } +
-}; +
-</code>+
  
 <code cpp Rectangle.cpp> <code cpp Rectangle.cpp>
 #include <iostream> #include <iostream>
-#include <cstdlib> 
-#include <ctime> 
 using namespace std; using namespace std;
- 
-#include "Point.cpp" 
  
 class Rectangle { class Rectangle {
   private:   private:
     int width, height;     int width, height;
-    Point *origin; 
   public:   public:
-    Rectangle(int w, int h, Point p); +    Rectangle(int width, int height); 
-    Rectangle(int s, Point p); +    void setWidth(int width); 
-    Rectangle(); +    void setHeight(int height); 
-    ~Rectangle(); +    int getWidth(); 
-    void setOrigin(Point &p); +    int getHeight();
-    Point &getOrigin();+
 }; };
  
-Rectangle::Rectangle(int w, int h, Point p) { +Rectangle::Rectangle(int width, int height) { 
-  width = w; height = h; +  this->width = widththis->height = height;
-  origin = new (nothrow) Point( p.getX(), p.getY() ); +
-  if(origin == NULL) { +
-    cerr << "Memory allocation failure!\n"; +
-    exit(-1); +
-  }+
 } }
  
-Rectangle::~Rectangle() { +void Rectangle::setWidth(int width) { this->width = width; } 
-  delete origin; +void Rectangle::setHeight(int height) { this->height height} 
-} +int Rectangle::getWidth() { return width; } 
- +int Rectangle::getHeight() { return height; }
-void Rectangle::setOrigin(Point &p) {  +
-  if(origin!=NULL) +
-    delete origin+
-   +
-  origin = new (nothrow) Point( p.getX(), p.getY() ); +
-  if(origin == NULL) { +
-    cerr << "Memory allocation failure!\n"; +
-    exit(-1); +
-  +
-+
- +
-Point &Rectangle::getOrigin() { return *origin; }+
  
 int main() { int main() {
-  const Point p(5,6); +  const Rectangle rect(10,5);  
-  const Rectangle rect(1,2,p);+
 } }
 </code> </code>
  
-Στον παραπάνω κώδικα επιχειρήστε να διαβάσετε το πεδίο //origin//, ως εξής:+Στον παραπάνω κώδικα επιχειρήστε να διαβάσετε την μεταβλητή //width//, ως εξής:
  
 <code cpp> <code cpp>
 int main() { int main() {
-  const Point p(5,6); +  const Rectangle rect(10,5); 
-  const Rectangle rect(1,2,p); +  cout << rect.getWidth();
-  Point p1 = rect.getOrigin();+
 } }
 </code> </code>
  
-Σε αυτή την περίπτωση λαμβάνετε το παρακάτω μήνυμα λάθους:+Σε αυτή την περίπτωση λαμβάνετε το παρακάτω μήνυμα λάθους από το μεγαγλωττιστή:
 <code> <code>
-Rectangle.cpp: In function ‘int main()’: +Rectangle5.cpp: In function ‘int main()’:                                                                                                                                                                           
-Rectangle.cpp:46:35: error: passing ‘const Rectangle’ as ‘this’ argument of ‘Point& Rectangle::getOrigin()’ discards qualifiers [-fpermissive] +Rectangle5.cpp:26:25: error: passing ‘const Rectangle’ as ‘this’ argument of ‘int Rectangle::getWidth()’ discards qualifiers [-fpermissive]                                                                         
-   const Point p1 = rect.getOrigin(); +   cout << rect.getWidth();                                                                                                                                                                                         
-                                   ^+                         ^
 </code> </code>
  
-Η επεξήγηση του παραπάνω μηνύματος είναι ότι εφόσον το αντικείμενο είναι //const// θα πρέπει και οι μέθοδοι που χρησιμοποιούμε για να προσπελάσουμε το αντικείμενο να είναι δηλωμένες ως //const//, δηλαδή να δηλώνουν ότι δεν μεταβάλλουν το αντικείμενο κατά την εκτέλεση τους. Ο διορθωμένος κώδικας δηλώνει ως //const// τη συνάρτηση //getOrigin// και έχει ως εξής:+Η επεξήγηση του παραπάνω μηνύματος είναι ότι εφόσον το αντικείμενο είναι //const// θα πρέπει και η μέθοδοι που χρησιμοποιούμε για να προσπελάσουμε το αντικείμενο να είναι const, δηλαδή να δηλώνουν ότι δεν μεταβάλλουν το αντικείμενο κατά την εκτέλεση τους. Ο διορθωμένος κώδικας δηλώνει τις συναρτήσεις  //getWidth// και //getHeight// ως //const// και έχει ως εξής:
  
-<code cpp> +<code cpp Rectangle.cpp> 
-Point &Rectangle::getOrigin() const { return *origin; } +#include <iostream> 
-</code>+using namespace std;
  
-===== Επιστρεφόμενη τιμή const συναρτήσεων =====+class Rectangle { 
 +  private: 
 +    int width, height; 
 +  public: 
 +    Rectangle(int width, int height); 
 +    void setWidth(int width); 
 +    void setHeight(int height); 
 +    int getWidth() const
 +    int getHeight() const; 
 +};
  
-Στον παραπάνω κώδικα αν και η συνάρτηση //getOrigin// δεν μεταβάλλει το αντικείμενο κατά την κλάση τηςτο αντικείμενο μπορεί να μεταβληθεί αμέσως μετά την κλήση αυτής ως εξής:+Rectangle::Rectangle(int widthint height) { 
 +  this->width = width; this->height = height; 
 +
 + 
 +void Rectangle::setWidth(int width) { this->width = width; } 
 +void Rectangle::setHeight(int height) { this->height = height; } 
 +int Rectangle::getWidth() const { return width; } 
 +int Rectangle::getHeight() const { return height; }
  
-<code cpp> 
 int main() { int main() {
-  const Point p(5,6); +  const Rectangle rect(10,5); 
-  const Rectangle rect(1,2,p); +  cout << rect.getWidth();
-  Point p1 = rect.getOrigin(); +
-  p1.setX(p1.getX()+1);+
 } }
-<code cpp>+</code> 
 + 
 +===== Υπερφόρτωση const και non-const συναρτήσεων =====
  
-Για να αποφύγουμε τα παραπάνω πρόβληματα είναι καλό να δηλώσουμε την επιστρεφόμενη τιμή της getOrigin ως //const//. Σε αυτή την περίπτωση η επιστρεφόμενη τιμή θα πρέπει με τη σειρά της να ανατεθεί σε ένα αντικείμενο τύπου const. Ο συνολικός κώδικας έχει ως εξής:+Στον παραπάνω κώδικα μπορείτε να έχετε δύο εκδόσεις για τις συναρτήσεις getWidth() και getHeight() μία που εφαρμόζεται σε const και μία που εφαρμόζεται σε non-const αντικείμενα ως εξής:
  
 <code cpp Rectangle.cpp> <code cpp Rectangle.cpp>
 #include <iostream> #include <iostream>
-#include <cstdlib> 
-#include <ctime> 
 using namespace std; using namespace std;
- 
-#include "Point.cpp" 
  
 class Rectangle { class Rectangle {
   private:   private:
     int width, height;     int width, height;
-    Point *origin; 
   public:   public:
-    Rectangle(int w, int h, Point p); +    Rectangle(int width, int height); 
-    Rectangle(int s, Point p); +    void setWidth(int width); 
-    Rectangle(); +    void setHeight(int height); 
-    ~Rectangle(); +    int getWidth() const
-    void setOrigin(Point &p); +    int getHeight() const
-    const Point &getOrigin() const;+    int getWidth() ; 
 +    int getHeight();
 }; };
  
-Rectangle::Rectangle(int w, int h, Point p) { +Rectangle::Rectangle(int width, int height) { 
-  width = w; height = h; +  this->width = widththis->height = height;
-  origin = new (nothrow) Point( p.getX(), p.getY() ); +
-  if(origin == NULL) { +
-    cerr << "Memory allocation failure!\n"; +
-    exit(-1); +
-  }+
 } }
  
-Rectangle::~Rectangle() { +void Rectangle::setWidth(int width) { this->width = width; } 
-  delete origin+void Rectangle::setHeight(int height) { this->height = height; } 
-}+int Rectangle::getWidth() const { cout << "I am the const method\n"return width; } 
 +int Rectangle::getHeight() const { return height; } 
 +int Rectangle::getWidth() { cout << "I am the non-const method\n"; return width; } 
 +int Rectangle::getHeight() { return height; }
  
-void Rectangle::setOrigin(Point &p) {  +int main() { 
-  if(origin!=NULL) +  const Rectangle rect1(10,5); 
-    delete origin+  Rectangle rect2(10,5); 
-   +  cout << "rect1 width: " << rect1.getWidth() << endl; 
-  origin = new (nothrow) Point( p.getX()p.getY() ); +  cout << "rect2 width: << rect2.getWidth() << endl;
-  if(origin == NULL{ +
-    cerr << "Memory allocation failure!\n"+
-    exit(-1); +
-  }+
 } }
 +</code>
 +
 +<WRAP center round tip 80%>
 +Στο παραπάνω παράδειγμα, η ύπαρξη της //non-const// μεθόδου στο συγκεκριμένο παράδειγμα είναι πλεονασμός καθώς η //const// μέθοδος μπορεί να κληθεί και από //non-const// αντικείμενα. Όπως δείξαμε ο περιορισμός ισχύει κατά το αντίστροφο, δηλαδή ένα //const// αντικείμενο δεν μπορεί να καλέσει μία //non-const// μέθοδο.
 +</WRAP>
 +
  
-const Point &Rectangle::getOrigin() const { return *origin; } 
  
-int main() { 
-  const Point p(5,6); 
-  const Rectangle rect(1,2,p); 
-  const Point p1 = rect.getOrigin(); 
-} 
-</code> 
-int main() { 
-  const Point p(5,6); 
-  const Rectangle rect(1,2,p); 
-  const Point p1 = rect.getOrigin(); 
-} 
-</code> 
-<code> 
  
cpp/const_member_functions.txt · Last modified: 2021/05/07 07:50 (external edit)