This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision | Next revision Both sides next revision | ||
|
cpp:constructors_destructors [2020/04/08 09:33] |
cpp:constructors_destructors [2020/04/08 10:21] gthanos |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Κατασκευαστές και καταστροφείς της κλάσης ====== | ||
| + | |||
| + | Στο προηγούμενο παράδειγμα της κλάσης // | ||
| + | |||
| + | <code cpp Rectangle.hpp> | ||
| + | #include < | ||
| + | using namespace std; | ||
| + | |||
| + | class Rectangle { | ||
| + | private: | ||
| + | int width, height; | ||
| + | public: | ||
| + | Rectangle(int w, int h); | ||
| + | void setWidth(int w); | ||
| + | void setHeight(int h); | ||
| + | int getWidth() const; | ||
| + | int getHeight() const; | ||
| + | }; | ||
| + | |||
| + | Rectangle:: | ||
| + | width = w; height = h; | ||
| + | } | ||
| + | |||
| + | void Rectangle:: | ||
| + | void Rectangle:: | ||
| + | int Rectangle:: | ||
| + | int Rectangle:: | ||
| + | </ | ||
| + | |||
| + | <code cpp RectangleUsage.cpp> | ||
| + | #include " | ||
| + | |||
| + | int main () { | ||
| + | Rectangle rect(5,6); | ||
| + | cout << "area: " << rect.getWidth() * rect.getHeight() << endl; | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <WRAP center round info 80%> | ||
| + | Σε αναλογία με τις μεθόδους ο κατασκευαστής μπορεί να οριστεί εντός της κλάσης, | ||
| + | <code c++ Rectangle.cpp> | ||
| + | class Rectangle { | ||
| + | private: | ||
| + | int width, height; | ||
| + | public: | ||
| + | Rectangle(int w, int h){ | ||
| + | width = w; height = h; | ||
| + | } | ||
| + | }; | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | ===== Default κατασκευαστής ===== | ||
| + | |||
| + | Εάν δεν οριστεί κανένας κατασκευαστής σε μία κλάση τότε για την κλάση ορίζεται από τον μεταγλωττιστή ο //default// κατασκευαστής. Ο κατασκευαστής αυτός δεν έχει ορίσματα. Τα πεδία της κλάσης αρχικοποιούνται ως εξής: | ||
| + | - για πεδία που έχουν βασικού τύπους (int, double, char κλπ) οι τιμές είναι τυχαίες. | ||
| + | - για πεδία που περιγράφονται από κλάσεις καλείται ο //default// κατασκευαστής της εκάστοτε κλάσης. | ||
| + | |||
| + | Εάν έχετε δηλώσει τουλάχιστον ένα κατασκευαστή που δεν είναι ο //default// κατασκευαστής χωρίς παραμέτρους τότε ο // | ||
| + | |||
| + | ===== Υπερφόρτωση κατασκευαστών ===== | ||
| + | |||
| + | Σε αναλογία με την [[cpp: | ||
| + | |||
| + | <code cpp Rectangle.hpp> | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | 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() const; | ||
| + | int getHeight() const; | ||
| + | }; | ||
| + | |||
| + | Rectangle:: | ||
| + | width = w; height = h; | ||
| + | } | ||
| + | |||
| + | Rectangle:: | ||
| + | width = s; height = s; | ||
| + | } | ||
| + | |||
| + | Rectangle:: | ||
| + | srand(time(NULL)); | ||
| + | width = rand() % 10 + 1; height = rand() % 10 + 1; | ||
| + | } | ||
| + | |||
| + | void Rectangle:: | ||
| + | void Rectangle:: | ||
| + | int Rectangle:: | ||
| + | int Rectangle:: | ||
| + | |||
| + | </ | ||
| + | |||
| + | <code cpp RectangleUsage.cpp> | ||
| + | #include " | ||
| + | |||
| + | int main () { | ||
| + | Rectangle rect(5,6); | ||
| + | cout << "area: " << rect.getWidth() * rect.getHeight() << endl; | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ===== Χρήση member initialization list για την αρχικοποίηση των μελών της κλάσης ===== | ||
| + | |||
| + | Παραπάνω συναντήσαμε τον κατασκευαστή με δύο ορίσματα | ||
| + | <code cpp> | ||
| + | Rectangle:: | ||
| + | width = w; height = h; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Αντί για την παραπάνω δήλωση θα μπορούσατε να γράψετε ισοδύναμα: | ||
| + | <code cpp> | ||
| + | Rectangle:: | ||
| + | height = h; | ||
| + | } | ||
| + | </ | ||
| + | ή | ||
| + | <code cpp> | ||
| + | Rectangle:: | ||
| + | </ | ||
| + | |||
| + | Τελικά η κλάση Rectangle μπορεί να γραφεί ως εξής: | ||
| + | |||
| + | <code cpp Rectangle.hpp> | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | 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() const; | ||
| + | int getHeight() const; | ||
| + | }; | ||
| + | |||
| + | Rectangle:: | ||
| + | } | ||
| + | |||
| + | Rectangle:: | ||
| + | } | ||
| + | |||
| + | Rectangle:: | ||
| + | srand(time(NULL)); | ||
| + | width = rand() % 10 + 1; height = rand() % 10 + 1; | ||
| + | } | ||
| + | |||
| + | void Rectangle:: | ||
| + | void Rectangle:: | ||
| + | int Rectangle:: | ||
| + | int Rectangle:: | ||
| + | </ | ||
| + | |||
| + | ===== Κλήση ενός κατασκευαστή μέσα από άλλο κατασκευαστή ===== | ||
| + | |||
| + | Συχνά μπορεί να θέλουμε να καλέσουμε μέσα από ένα κατασκευαστή έναν άλλο κατασκευαστή. Μπορείτε να το κάνετε αυτό χρησιμοποιώντας ως οποιαδήποτε άλλη μέθοδο. Στο προηγούμενο παράδειγμα, | ||
| + | |||
| + | <code cpp> | ||
| + | Rectangle:: | ||
| + | Rectangle(s, | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | O ίδιος κώδικας με χρήση // | ||
| + | |||
| + | <code cpp> | ||
| + | Rectangle:: | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ===== Αρχικοποίηση αντικειμένων που περιέχουν πεδία που περιγράφονται από κλάσεις ===== | ||
| + | |||
| + | Στην προηγούμενη ενότητα είδαμε την κλάση Cuboid που περιγράφει την κλάση του κυβοειδούς και περιέχει ένα πεδίο τύπου Rectangle. Εδώ θα δούμε πως μπορούμε να ορίσουμε ένα ή περισσότερους κατασκευαστές για τη συγκεκριμένη κλάση. | ||
| + | |||
| + | <code cpp Cuboid.hpp> | ||
| + | #include < | ||
| + | using namespace std; | ||
| + | |||
| + | #include " | ||
| + | |||
| + | class Cuboid { | ||
| + | private: | ||
| + | int length; | ||
| + | Rectangle rect; | ||
| + | public: | ||
| + | Cuboid(int w, int h, int l); | ||
| + | Cuboid(Rectangle r, int l); | ||
| + | | ||
| + | void setRectangle(Rectangle r); | ||
| + | Rectangle getRectangle() const; | ||
| + | void setLength(int l); | ||
| + | int getLength() const; | ||
| + | int volume(); | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | <code cpp Cuboid.cpp> | ||
| + | include " | ||
| + | |||
| + | Cuboid:: | ||
| + | rect.setWidth(w); | ||
| + | rect.setHeight(h); | ||
| + | length = l; | ||
| + | } | ||
| + | |||
| + | Cuboid:: | ||
| + | rect = r; | ||
| + | | ||
| + | } | ||
| + | |||
| + | void Cuboid:: | ||
| + | Rectangle Cuboid:: | ||
| + | void Cuboid:: | ||
| + | int Cuboid:: | ||
| + | |||
| + | int Cuboid:: | ||
| + | return length * rect.getWidth() * rect.getHeight(); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Οι παραπάνω δύο κατασκευαστές με χρήση member initilization list μπορούν να γραφούν ως εξής: | ||
| + | |||
| + | Παρατηρήστε πως ορίζονται οι κατασκευαστές της κλάσης //Cuboid// με χρήση //member initialization list// | ||
| + | < | ||
| + | Cuboid:: | ||
| + | Cuboid:: | ||
| + | </ | ||
| + | |||
| + | Στην 1η περίπτωση γίνεται ανάθεση του αντικειμένου //r// στο πεδίο //rect//. Στην 2η περίπτωση καλείται ο κατασκευαστής της κλάσης // | ||
| + | |||
| + | ===== Καταστροφέας της κλάσης ===== | ||
| + | |||
| + | Σε αναλογία με τον κατασκευαστή της κλάσης η C++ δηλώνει και τον καταστροφέα της κλάσης. Ο καταστροφέας της κλάσης επιτρέπει να γίνουν οι απαραίτητες εργασίες καθαρισμού για το αντικείμενο που καταστρέφεται. Για παράδειγμα είναι πιθανόν κατά την δημιουργία του αντικειμένου να έχει δεσμευθεί μνήμη την οποία πρέπει να ελευθερώσουμε ή να έχουν ανοιχθεί αρχεία τα οποία κατά την καταστροφή του αντικειμένου πρέπει να τα κλείσουμε. | ||
| + | |||
| + | Στο παρακάτω παράδειγμα βλέπετε την κλάση // | ||
| + | |||
| + | <code cpp Rectangle.cpp> | ||
| + | #include < | ||
| + | #include < | ||
| + | using namespace std; | ||
| + | |||
| + | class Rectangle { | ||
| + | private: | ||
| + | int *width, *height; | ||
| + | public: | ||
| + | Rectangle(int w, int h); | ||
| + | ~Rectangle(); | ||
| + | void setWidth(int w); | ||
| + | void setHeight(int h); | ||
| + | int getWidth(); | ||
| + | int getHeight(); | ||
| + | }; | ||
| + | |||
| + | Rectangle:: | ||
| + | width = new (nothrow) int; | ||
| + | height = new (nothrow) int; | ||
| + | if(width == NULL || height == NULL) { | ||
| + | cerr << " | ||
| + | exit(-1); | ||
| + | } | ||
| + | *width = w; *height = h; | ||
| + | cout << " | ||
| + | } | ||
| + | |||
| + | Rectangle:: | ||
| + | cout << " | ||
| + | delete width; | ||
| + | delete height; | ||
| + | } | ||
| + | |||
| + | void Rectangle:: | ||
| + | void Rectangle:: | ||
| + | int Rectangle:: | ||
| + | int Rectangle:: | ||
| + | |||
| + | int main () { | ||
| + | Rectangle rect(5,6); | ||
| + | cout << "area: " << rect.getWidth() * rect.getHeight() << endl; | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||