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 11:22] gthanoscpp:copy_constructors [2017/04/20 12:16] – [Ορισμός ενός κατασκευαστή αντιγραφέα] gthanos
Line 1: Line 1:
 ====== Κατασκευαστές Αντιγραφείς ====== ====== Κατασκευαστές Αντιγραφείς ======
  
-Στην ενότητα των συναρτήσεων είδαμε [[cpp:functions#κλήση_με_τιμή_και_κλήση_με_αναφορά|την κλήση με τιμή και κλήση με αναφορά]] προκειμένου να περάσουμε παραμέτρους σε μία συνάρτηση. Κατά την κλήση με τιμή όταν η παράμετρος είναι ένα αντικείμενο, ένα αντίγραφο του αντικειμένου θα πρέπει να δημιουργηθεί στο //stack// της συνάρτησης που καλείται. Προκειμένου να γίνει αυτό η C++ ορίζει την έννοια του κατασκευαστή αντιγραφέα ο οποίος έχει την δυνατότητα να δημιουργήσει ένα αντικείμενο που είναι ακριβές αντίγραφο ενός άλλου αντικειμένου. Δείτε το παρακάτω παράδειγμα της μεθόδου //printArea// η οποία λαμβάνει ως παράμετρο ένα αντικείμενο της κλάσης //Rectangle//.+Στην ενότητα των συναρτήσεων είδαμε [[cpp:functions#κλήση_με_τιμή_και_κλήση_με_αναφορά|την κλήση με τιμή και κλήση με αναφορά]] προκειμένου να περάσουμε παραμέτρους σε μία συνάρτηση. Κατά την κλήση με τιμή όταν η παράμετρος είναι ένα αντικείμενο, ένα αντίγραφο του αντικειμένου θα πρέπει να δημιουργηθεί στο //stack// της συνάρτησης που καλείται. Προκειμένου να γίνει αυτό η C++ ορίζει την έννοια του κατασκευαστή αντιγραφέα (//copy constructor//), ο οποίος δημιουργεί ένα αντικείμενο που είναι ακριβές αντίγραφο ενός άλλου αντικειμένου. Δείτε το παρακάτω παράδειγμα της μεθόδου //printArea// η οποία λαμβάνει ως παράμετρο ένα αντικείμενο της κλάσης //Rectangle//.
  
 <code cpp foo.cpp> <code cpp foo.cpp>
Line 18: Line 18:
 </code> </code>
  
-Παρακάτω δίνεται το σχηματικό διάγραμμα της στοίβας της διεργασίας πριν και κατά τη διάρκεια της κλήσης της μεθόδου //printArea//Διακρίνεται η αντιγραφή του αντικειμένου //rect// στη στοίβα της //printArea// κατά την κλήση της.+Παρακάτω δίνεται το σχηματικό διάγραμμα της στοίβας της διεργασίας πριν και κατά τη διάρκεια της κλήσης της μεθόδου //printArea//Κατά την κλήση της συνάρτησης //printArea//, διακρίνεται η αντιγραφή του αντικειμένου //rect// στη μεταβλητή //r// που ανήκει στη στοίβα της //printArea//.
  
 {{ :cpp:cppstackcopyconstructor.png |}} {{ :cpp:cppstackcopyconstructor.png |}}
 +
 +===== Ορισμός ενός κατασκευαστή αντιγραφέα =====
 +
 +Ένας κατασκευαστής αντιγραφέας για την κλάση Rectangle ορίζεται ως εξής:
 +
 +<code cpp>
 +Rectangle::Rectangle(Rectangle &r) {
 +  width = r.width; height = r.height;
 +}
 +</code>
 +
 +Συνολικά η κλάση //Rectangle// διαμορφώνεται ως εξής:
 +
 +<code cpp Rectangle.cpp>
 +#include <iostream>
 +#include <cstdlib>
 +#include <ctime>
 +using namespace std;
 +
 +class Rectangle {
 +  private:
 +    int width, height;
 +  public:
 +    Rectangle(int w, int h);
 +    Rectangle(int s);
 +    Rectangle();
 +    void setWidth(int w);
 +    void setHeight(int h);
 +    int getWidth();
 +    int getHeight();
 +};
 +
 +Rectangle::Rectangle(int w, int h) {
 +  width = w; height = h;
 +}
 +
 +Rectangle::Rectangle(int s) {
 +  width = s; height = s;
 +}
 +
 +Rectangle::Rectangle() {
 +  srand(time(NULL));
 +  width = rand() % 10 + 1; height = rand() % 10 + 1;
 +}
 +
 +// copy constructor
 +Rectangle::Rectangle(Rectangle &r) {
 +  width = r.width; height = r.height;
 +}
 +
 +void Rectangle::setWidth(int w) { width = w; }
 +void Rectangle::setHeight(int h) { height = h; }
 +int Rectangle::getWidth() { return width; }
 +int Rectangle::getHeight() { return height; }
 +</code>
 +
 +<WRAP center round tip 60%>
 +Εάν δεν ορίσετε ένα δικό σας κατασκευαστή αντιγραφέα ο //compiler// δημιουργεί έναν από μόνος του αντιγράφοντας τα περιεχόμενα του αρχικού αντικειμένου στο νέο πεδίο προς πεδίο.
 +</WRAP>
 +
 +==== Δημιουργία κατασκευαστών αντιγραφέων ====
 +
 +Στις περιπτώσεις που υπάρχουν πεδία δείκτες που δείχνουν σε άλλα αντικείμενα (στατικά ή δυναμικά δεσμευμένα) αντιγράφονται οι διευθύνσεις αυτές, όπως θα αντιγράφονταν οποιοδήποτε άλλο πεδίο. Αυτό πρακτικά σημαίνει ότι δύο ή περισσότερα αντικείμενα δείχνουν σε μία κοινή περιοχή μνήμης. Το παραπάνω μπορεί να προκαλέσει δυσλειτουργίες καθώς η μεταβολή του κοινού αντικειμένου επηρεάζει το σύνολο των αντικειμένων που το μοιράζονται.
 +
 +Στο παρακάτω παράδειγμα ορίζουμε την κλάση //Point// η οποία αντιπροσωπεύει ένα σημείο στο διδιάστατο χώρο.
 +
 +<code cpp Point.cpp>
 +#include <iostream>
 +using namespace std;
 +
 +class Point {
 +    int x, y;
 +  public:
 +    Point(int vx,int vy) { x = vx; y = vy; cout << "Point regular constructor!\n"; }
 +    Point(const Point &p) { x = p.x; y = p.y; cout << "Point copy constructor!\n"; }      
 +    Point() { cout << "Point default constructor!\n"; }
 +    ~Point() { cout << "xP Point destructor!\n"; }
 +    void setX(int vx) { x = vx; }
 +    void setY(int vy) { y = vy; }
 +    int getX() { return x; }
 +    int getY() { return y; }
 +};
 +</code>
 +
 +Η κλάση //Rectangle// που ακολουθεί ορίζει ένα πεδίο δείκτη σε αντικείμενα τύπου //Point//. Η δημιουργία ενός αντικειμένου τύπου //Rectangle// συνεπάγεται τη δυναμική δέσμευση μνήμης για το αντικείμενο τύπου //Point// που αυτή περιέχει. Δείτε το παράδειγμα που ακολουθεί.
 +
 +<code cpp Rectangle.cpp>
 +#include <iostream>
 +#include <cstdlib>
 +#include <ctime>
 +using namespace std;
 +
 +#include "Point.cpp"
 +
 +class Rectangle {
 +  private:
 +    int width, height;
 +    Point *origin;
 +  public:
 +    Rectangle(int w, int h, Point *p);
 +    Rectangle(int s, Point *p);
 +    Rectangle();
 +    void setWidth(int w);
 +    void setHeight(int h);
 +    int getWidth();
 +    int getHeight();
 +};
 +
 +Rectangle::Rectangle(int w, int h, Point *p) {
 +  width = w; height = h;
 +  origin = p;
 +}
 +
 +Rectangle::Rectangle(int s, Point *p) {
 +  width = s; height = s;
 +  origin = p;
 +}
 +
 +Rectangle::Rectangle() {
 +  srand(time(NULL));
 +  width = rand() % 10 + 1; height = rand() % 10 + 1;
 +  origin = new (nothrow) Point{};
 +  if(origin == NULL) {
 +    cerr << "Memory allocation failure!\n";
 +    exit(-1);
 +  }
 +}
 +
 +void Rectangle::setWidth(int w) { width = w; }
 +void Rectangle::setHeight(int h) { height = h; }
 +int Rectangle::getWidth() { return width; }
 +int Rectangle::getHeight() { return height; }
 +</code>
 +
 +<code cpp MoveOrigin.cpp>
 +
 +#include "Rectangle.cpp"
 +
 +
 +
 +int main() {
 +  Point *p = new Point(10,5);
 +  Rectangle r1(5,6,p);
 +  
 +  Rectangle rect(5,6,4,1);
 +}
 +
 +</code>
 +
 +
 +
 +
  
  
  
cpp/copy_constructors.txt · Last modified: 2022/05/12 19:41 by gthanos