This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
cpp:constructors_destructors [2017/04/16 05:03] gthanos [Χρήση member initialization list για την αρχικοποίηση των μελών της κλάσης] |
cpp:constructors_destructors [2020/04/08 09:33] |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Κατασκευαστές και καταστροφείς της κλάσης ====== | ||
| - | |||
| - | Στο προηγούμενο παράδειγμα της κλάσης // | ||
| - | |||
| - | <code c++ Rectangle.cpp> | ||
| - | #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(); | ||
| - | int getHeight(); | ||
| - | }; | ||
| - | |||
| - | Rectangle:: | ||
| - | width = w; height = h; | ||
| - | } | ||
| - | |||
| - | void Rectangle:: | ||
| - | void Rectangle:: | ||
| - | int Rectangle:: | ||
| - | int Rectangle:: | ||
| - | |||
| - | int main () { | ||
| - | Rectangle rect(5,6); | ||
| - | cout << "area: " << rect.getWidth() * rect.getHeight() << endl; | ||
| - | return 0; | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | <WRAP center round tip 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// κατασκευαστής χωρίς παραμέτρους τότε ο μεταγλωττιστής δεν κατασκευάζει αυτόματα τον //default// κατασκευαστή. Σε περίπτωση που ο //default// κατασκευαστής απαιτείται λαμβάνετε μήνυμα λάθους από τον μεταγλωττιστή. | ||
| - | |||
| - | ===== Υπερφόρτωση κατασκευαστών ===== | ||
| - | |||
| - | Σε αναλογία με την [[cpp: | ||
| - | |||
| - | <code c++ Rectangle.cpp> | ||
| - | #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(); | ||
| - | int getHeight(); | ||
| - | }; | ||
| - | |||
| - | 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:: | ||
| - | |||
| - | int main () { | ||
| - | Rectangle rect(5,6); | ||
| - | cout << "area: " << rect.getWidth() * rect.getHeight() << endl; | ||
| - | return 0; | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | ===== Χρήση member initialization list για την αρχικοποίηση των μελών της κλάσης ===== | ||
| - | |||
| - | Παραπάνω συναντήσαμε τον κατασκευαστή με δύο ορίσματα | ||
| - | <code c++> | ||
| - | Rectangle:: | ||
| - | width = w; height = h; | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | Αντί για την παραπάνω δήλωση θα μπορούσατε να γράψετε ισοδύναμα: | ||
| - | <code c++> | ||
| - | Rectangle:: | ||
| - | height = h; | ||
| - | } | ||
| - | </ | ||
| - | ή | ||
| - | <code c++> | ||
| - | Rectangle:: | ||
| - | </ | ||
| - | |||
| - | Ο παραπάνω τρόπος αρχικοποίησης μπορεί να επεκταθεί και να χρησιμοποιηθεί για την κλήση κατασκευαστών των πεδίων της κλάσης, | ||
| - | |||
| - | <code c++ Cuboid.cpp> | ||
| - | #include < | ||
| - | using namespace std; | ||
| - | |||
| - | #include " | ||
| - | |||
| - | class Cuboid { | ||
| - | private: | ||
| - | int length; | ||
| - | Rectangle rect; | ||
| - | public: | ||
| - | Cuboid(Rectangle r, int l); | ||
| - | Cuboid(int w, int h, int l); | ||
| - | void setRectangle(Rectangle r) {rect = r;} | ||
| - | Rectangle getRectangle() {return rect;} | ||
| - | void setLength(int l) { length = l; } | ||
| - | int getLength() { return length; } | ||
| - | int volume(); | ||
| - | }; | ||
| - | |||
| - | Cuboid:: | ||
| - | Cuboid:: | ||
| - | |||
| - | int Cuboid:: | ||
| - | return length * rect.getWidth() * rect.getHeight(); | ||
| - | } | ||
| - | |||
| - | int main () { | ||
| - | //Rectangle rect(5,6); | ||
| - | //Cuboid cuboid(rect, | ||
| - | Cuboid cuboid(2, | ||
| - | cout << " | ||
| - | return 0; | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | Παρατηρήστε πως ορίζονται οι κατασκευαστές της κλάσης //Cuboid// με χρήση //member initialization list// | ||
| - | < | ||
| - | Cuboid:: | ||
| - | Cuboid:: | ||
| - | </ | ||
| - | |||
| - | Στην 1η περίπτωση γίνεται ανάθεση του αντικειμένου //r// στο πεδίο //rect//. Στην 2η περίπτωση καλείται ο κατασκευαστής της κλάσης // | ||
| - | |||
| - | Για να μεταγλωττίσετε και να εκτελέσετε το παραπάνω πρόγραμμα βάλτε σε σχόλια τη μέθοδο //main// της κλάσης Rectangle. | ||
| - | ===== Καταστροφέας της κλάσης ===== | ||
| - | |||
| - | Σε αναλογία με τον κατασκευαστή της κλάσης η C++ δηλώνει και τον καταστροφέα της κλάσης. Ο καταστροφέας της κλάσης επιτρέπει να γίνουν οι απαραίτητες εργασίες καθαρισμού για το αντικείμενο που καταστρέφεται. Για παράδειγμα είναι πιθανόν κατά την δημιουργία του αντικειμένου να έχει δεσμευθεί μνήμη την οποία πρέπει να ελευθερώσουμε ή να έχουν ανοιχθεί αρχεία τα οποία κατά την καταστροφή του αντικειμένου πρέπει να τα κλείσουμε. | ||
| - | |||
| - | Στο παρακάτω παράδειγμα βλέπετε την κλάση // | ||
| - | |||
| - | <code c++ 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; | ||
| - | } | ||
| - | |||
| - | Rectangle:: | ||
| - | 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; | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | ===== Δημιουργία Αντικειμένων ===== | ||
| - | |||
| - | Η δημιουργία αντικειμένων γίνεται με κλήση του αντίστοιχου κατασκευαστή ως εξής: | ||
| - | <code c++> | ||
| - | Rectangle rect1(3,4); | ||
| - | Rectangle rect2(5); | ||
| - | Rectangle rect3; | ||
| - | </ | ||
| - | |||
| - | Ο παραπάνω κώδικας δημιουργεί 3 αντικείμενα της κλάσης // | ||
| - | |||
| - | <WRAP center round tip 80%> | ||
| - | Παρατηρήστε ότι για το τελευταίο αντικείμενο δεν χρησιμοποιούνται παρενθέσεις κατά την κλήση του καστασκευαστή, | ||
| - | <code c++> | ||
| - | Rectangle rect3(); // this is an error | ||
| - | </ | ||
| - | Η χρήση παρενθέσεων είναι λανθασμένη με συνέπεια να λάγετε μήνυμα λάθους από τον μεταγλωττιστή. | ||
| - | </ | ||
| - | |||
| - | |||