User Tools

Site Tools


cpp:copy_constructors

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
Next revisionBoth sides next revision
cpp:copy_constructors [2017/04/20 12:20] – [Ορισμός ενός κατασκευαστή αντιγραφέα] gthanoscpp:copy_constructors [2017/05/10 06:58] – [Δημιουργία κατασκευαστών αντιγραφέων] gthanos
Line 77: Line 77:
 </code> </code>
  
-<WRAP center round tip 60%>+<WRAP center round tip 80%>
 Εάν δεν ορίσετε ένα δικό σας κατασκευαστή αντιγραφέα ο //compiler// δημιουργεί έναν από μόνος του αντιγράφοντας τα περιεχόμενα του αρχικού αντικειμένου στο νέο πεδίο προς πεδίο. Εάν δεν ορίσετε ένα δικό σας κατασκευαστή αντιγραφέα ο //compiler// δημιουργεί έναν από μόνος του αντιγράφοντας τα περιεχόμενα του αρχικού αντικειμένου στο νέο πεδίο προς πεδίο.
 </WRAP> </WRAP>
  
-Μία άλλη περίπτωση κατά την οποία θα κληθεί o κατασκευαστής αντιγραφέας είναι η παρακάτω. Εδώ μαζί με την δήλωση της μεταβλητής γίνεται ανάθεση των πεδίων του αντικειμένου //r1// στο //r2//+Μία άλλη περίπτωση κατά την οποία θα κληθεί o κατασκευαστής αντιγραφέας είναι η παρακάτω. Εδώ μαζί με την δήλωση της μεταβλητής καλείται ο κατασκευαστής αντιγραφέας του //r1// με όρισμα το //r2//
  
 <code cpp CopyRectangle.cpp> <code cpp CopyRectangle.cpp>
Line 92: Line 92:
 </code> </code>
  
-==== Δημιουργία κατασκευαστών αντιγραφέων ====+<WRAP center round tip 80%> 
 +Το παραπάνω είναι λειτουργικά ισοδύναμο με το παρακάτω. 
 +<code cpp CopyRectangle.cpp> 
 +#include "Rectangle.cpp" 
 + 
 +int main() { 
 +  Rectangle r1(5,6); 
 +  Rectangle r2; 
 +  r2 = r1; 
 +
 +</code> 
 +Για τον μεταγλωττιστή όμως οι κώδικες είναι διαφορετικοί. Στην πρώτη περίπτωση καλείται ο κατασκευαστής αντιγραφέας (//copy constructor//), ενώ στη 2η περίπτωση καλείται ο //default// κατασκευαστής και στη συνέχεια γίνεται ανάθεση των τιμών των πεδίων του //r1// στα πεδία του //r2//. 
 +</WRAP> 
 + 
 +===== Δημιουργία κατασκευαστών αντιγραφέων =====
  
 Στις περιπτώσεις που υπάρχουν πεδία δείκτες που δείχνουν σε άλλα αντικείμενα (στατικά ή δυναμικά δεσμευμένα) αντιγράφονται οι διευθύνσεις αυτές, όπως θα αντιγράφονταν οποιοδήποτε άλλο πεδίο. Αυτό πρακτικά σημαίνει ότι δύο ή περισσότερα αντικείμενα δείχνουν σε μία κοινή περιοχή μνήμης. Το παραπάνω μπορεί να προκαλέσει δυσλειτουργίες καθώς η μεταβολή του κοινού αντικειμένου επηρεάζει το σύνολο των αντικειμένων που το μοιράζονται. Στις περιπτώσεις που υπάρχουν πεδία δείκτες που δείχνουν σε άλλα αντικείμενα (στατικά ή δυναμικά δεσμευμένα) αντιγράφονται οι διευθύνσεις αυτές, όπως θα αντιγράφονταν οποιοδήποτε άλλο πεδίο. Αυτό πρακτικά σημαίνει ότι δύο ή περισσότερα αντικείμενα δείχνουν σε μία κοινή περιοχή μνήμης. Το παραπάνω μπορεί να προκαλέσει δυσλειτουργίες καθώς η μεταβολή του κοινού αντικειμένου επηρεάζει το σύνολο των αντικειμένων που το μοιράζονται.
Line 131: Line 145:
     Point *origin;     Point *origin;
   public:   public:
-    Rectangle(int w, int h, Point *p); +    Rectangle(int w, int h, Point p); 
-    Rectangle(int s, Point *p);+    Rectangle(int s, Point p);
     Rectangle();     Rectangle();
 +    ~Rectangle();
     void setWidth(int w);     void setWidth(int w);
     void setHeight(int h);     void setHeight(int h);
     int getWidth();     int getWidth();
     int getHeight();     int getHeight();
 +    void setOrigin(Point *p) { origin = p; }
 +    Point *getOrigin() { return origin; }
 }; };
  
-Rectangle::Rectangle(int w, int h, Point *p) {+Rectangle::Rectangle(int w, int h, Point p) {
   width = w; height = h;   width = w; height = h;
-  origin = p;+  origin = new (nothrow) Point( p.getX(), p.getY() ); 
 +  if(origin == NULL) { 
 +    cerr << "Memory allocation failure!\n"; 
 +    exit(-1); 
 +  }
 } }
  
-Rectangle::Rectangle(int s, Point *p) {+Rectangle::Rectangle(int s, Point p) {
   width = s; height = s;   width = s; height = s;
-  origin = p;+  origin = new (nothrow) Point( p.getX(), p.getY() ); 
 +  if(origin == NULL) { 
 +    cerr << "Memory allocation failure!\n"; 
 +    exit(-1); 
 +  }
 } }
  
Line 158: Line 183:
     exit(-1);     exit(-1);
   }   }
 +}
 +
 +Rectangle::~Rectangle() {
 +  delete origin;
 } }
  
Line 164: Line 193:
 int Rectangle::getWidth() { return width; } int Rectangle::getWidth() { return width; }
 int Rectangle::getHeight() { return height; } int Rectangle::getHeight() { return height; }
 +void Rectangle::setOrigin(Point *p) { origin = p; }
 +Point *Rectangle::getOrigin() { return origin; }
 </code> </code>
  
Line 170: Line 201:
 #include "Rectangle.cpp" #include "Rectangle.cpp"
  
 +int moveOrigin(Rectangle &r, int dx, int dy) {
 +  Point *p = r.getOrigin();
 +  p->setX(p->getX() + dx);
 +  p->setY(p->getY() + dy);
 +}
  
 +void print(Rectangle r) {
 +  cout << "[" << r.getOrigin().getX() << "," << r.getOrigin().getY() << "] ";
 +  cout << "width: " << r.getWidth() << ", height: " << getHeight() << endl;
 +}
  
 int main() { int main() {
-  Point *= new Point(10,5)+  Point p{10,5}
-  Rectangle r1(5,6,p);+  Rectangle r1{5,6,p};   
 +  Rectangle r2 = r1;
      
-  Rectangle rect(5,6,4,1);+  moveOrigin(r11,-1); 
 +  moveOrigin(r2, 2, 0);
 } }
- 
 </code> </code>
 +
 +Ο παραπάνω κώδικας αντιγράφει στο αντικείμενο //r2// τα πεδία του αντικειμένου //r1// πεδίο προς πεδίο. Αυτό σημαίνει ότι τα αντικείμενα //r1// και //r2// μοιράζονται το ίδιο αντικείμενο τύπου //Point//. Εάν μεταβληθούν οι συντεταγμένες του //Point// από το αντικείμενο //r1//, η μεταβολή θα ισχύει και για το αντικείμενο //r2//. Μετά την ολοκλήρωση κλήσης της πρώτης moveOrigin το αντίγραφο του αντικειμένου r1 θα καταστραφεί ελευθερώνοντας τη δεσμευμένη μνήμη για το πεδίο origin. Η αμέσως επόμενη κλήση της moveOrigin Θα παράγει segmentation fault.
 +Για να αποφύγετε την παραπάνω συμπεριφορά θα πρέπει να ορίσετε τον δικό σας κατασκευαστή αντιγραφέα που κάνει τα εξής:
 +  - Δημιουργεί ένα νέο αντικείμενο τύπου //Point//.
 +  - Αντιγράφει τα περιεχόμενα του παλιού στο νέο.
 +
 +Ο προτεινόμενος κατασκευαστής αντιγραφέας δίνεται παρακάτω:
 +<code cpp>
 +Rectangle::Rectangle(Rectangle &r) {
 +  width = r.width;
 +  height = r.height;
 +  origin = new (nothrow) Point(r.getOrigin()->getX(), r.getOrigin()->getY());
 +  if(origin == NULL) {
 +    cerr << "Memory allocation failure!";
 +    exit(-1);
 +  }
 +}
 +</code> 
 +
  
  
cpp/copy_constructors.txt · Last modified: 2022/05/12 19:41 by gthanos