Next revision | Previous revisionNext revisionBoth sides next revision |
cpp:constructors [2020/04/08 10:34] – created gthanos | cpp:constructors [2020/04/14 07:44] – [Χρήση member initialization list για την αρχικοποίηση των μελών της κλάσης] gthanos |
---|
====== Κατασκευαστές και καταστροφείς της κλάσης ====== | ====== Κατασκευαστές της κλάσης ====== |
| |
Στο προηγούμενο παράδειγμα της κλάσης //Rectangle// δεν δηλώθηκε κάποιος κατασκευαστής. Ο κατασκευαστής της κλάσης είναι μέθοδος που έχει το όνομα της κλάσης και δεν έχει επιστρεφόμενο τύπο. Ο ρόλος του κατασκευαστή της κλάσης είναι να αρχικοποιήσει τις τιμές των πεδίων της κλάσης. Σημειώστε, ότι ο κατασκευαστής της κλάσης στη C++ δεν δεσμεύει χώρο στη μνήμη, όπως συμβαίνει στη Java. Για την κλάση //Rectangle//, παρακάτω δηλώνεται ο κατασκευαστής ''Rectangle(int w, int h)''. | Στο προηγούμενο παράδειγμα της κλάσης //Rectangle// δεν δηλώθηκε κάποιος κατασκευαστής. Ο κατασκευαστής της κλάσης είναι συνάρτηση που έχει το όνομα της κλάσης και δεν έχει επιστρεφόμενο τύπο. Ο ρόλος του κατασκευαστή της κλάσης είναι να αρχικοποιήσει τις τιμές των πεδίων της κλάσης. Σημειώστε, ότι ο κατασκευαστής της κλάσης στη C++ δεν δεσμεύει χώρο στη μνήμη, όπως συμβαίνει στη Java. Για την κλάση //Rectangle//, παρακάτω δηλώνεται ο κατασκευαστής ''Rectangle(int w, int h)''. |
| |
<code cpp Rectangle.hpp> | <code cpp Rectangle.hpp> |
int getHeight() const; | int getHeight() const; |
}; | }; |
| </code> |
| |
| <code cpp Rectangle.cpp> |
| #include "Rectangle.hpp" |
| |
Rectangle::Rectangle(int w, int h) { | Rectangle::Rectangle(int w, int h) { |
width = w; height = h; | width = w; height = h; |
} | } |
| |
void Rectangle::setWidth(int w) { width = w; } | void Rectangle::setWidth(int w) { width = w; } |
void Rectangle::setHeight(int h) { height = h; } | void Rectangle::setHeight(int h) { height = h; } |
return 0; | return 0; |
} | } |
| </code> |
| |
| Για την μεταγλώττιση αρκεί να μεταγλωττισετε κάθε επιμέρους κλάση ξεχωριστά και στη συνέχεια να δημιουργήσετε το τελικό εκτελέσιμο. Στο συγκεκριμένο παράδειγμα, η διαδικασία είναι η παρακάτω και παράγει το εκτελέσιμο με όνομα **a.out**: |
| <code> |
| g++ -Wall -g Rectangle.cpp -c |
| g++ -Wall -g Rectangle.o RectangleUsage.cpp |
</code> | </code> |
| |
<WRAP center round info 80%> | <WRAP center round info 80%> |
Σε αναλογία με τις μεθόδους ο κατασκευαστής μπορεί να οριστεί εντός της κλάσης, όπως παρακάτω. Η δήλωση εντός της κλάσης συνεπάγεται τη δήλωση από τον προγραμματιστή του κατασκευαστή ως //inline//. | Σε αναλογία με τις μεθόδους ο κατασκευαστής μπορεί να οριστεί εντός της κλάσης, όπως παρακάτω. Η δήλωση εντός της κλάσης συνεπάγεται τη δήλωση από τον προγραμματιστή του κατασκευαστή ως //inline//. |
<code c++ Rectangle.cpp> | <code cpp Rectangle.cpp> |
class Rectangle { | class Rectangle { |
private: | private: |
===== Υπερφόρτωση κατασκευαστών ===== | ===== Υπερφόρτωση κατασκευαστών ===== |
| |
Σε αναλογία με την [[cpp:functions#υπερφόρτωση_συναρτήσεων|υπερφόρτωση συναρτήσεων]] η C++ υποστηρίζει και υπερφόρτωση κατασκευαστών. Συγκεκριμένα, μπορείτε να έχετε περισσότερους από έναν κατασκευαστές αρκεί αυτοί να έχουν διαφορετικό αριθμό ή τύπο ορισμάτων. Δείτε το παρακάτω παράδειγμα της κλάση //Rectangle//, όπου δίνονται δύο επιπλέον κατασκευαστές, ένα κατασκευαστή που λαμβάνει ένα κοινό όρισμα και για τις δύο διαστάσεις του παραλληλογράμμου και ένα κατασκευαστή χωρίς ορίσματα που αναθέτει τυχαίες τιμές στις διαστάσεις του παραλληλογράμμου. | Σε αναλογία με την [[cpp:functions#υπερφόρτωση_συναρτήσεων|υπερφόρτωση συναρτήσεων]] η C++ υποστηρίζει και υπερφόρτωση κατασκευαστών. Συγκεκριμένα, μπορείτε να έχετε περισσότερους από έναν κατασκευαστές αρκεί αυτοί να έχουν διαφορετικό αριθμό ή τύπο ορισμάτων. Δείτε το παρακάτω παράδειγμα της κλάση //Rectangle//, όπου δίνονται δύο επιπλέον κατασκευαστές, ένας κατασκευαστής που λαμβάνει ένα κοινό όρισμα και για τις δύο διαστάσεις του παραλληλογράμμου δημιουργώντας ένα τετράγωνο και ένας κατασκευαστής χωρίς ορίσματα που αναθέτει τυχαίες τιμές στα μήκη των πλευρών του παραλληλογράμμου. |
| |
<code cpp Rectangle.hpp> | <code cpp Rectangle.hpp> |
int getHeight() const; | int getHeight() const; |
}; | }; |
| </code> |
| |
| <code cpp Rectangle.cpp> |
| #include "Rectangle.hpp" |
| |
Rectangle::Rectangle(int w, int h) { | Rectangle::Rectangle(int w, int h) { |
</code> | </code> |
| |
Αντί για την παραπάνω δήλωση θα μπορούσατε να γράψετε ισοδύναμα: | Αντί για την παραπάνω δήλωση θα μπορούσατε να γράψετε __ισοδύναμα__: |
<code cpp> | <code cpp> |
Rectangle::Rectangle(int w, int h) : width(w) { | Rectangle::Rectangle(int w, int h) : width(w) { |
} | } |
</code> | </code> |
ή | ή __ισοδύναμα__ |
<code cpp> | <code cpp> |
Rectangle::Rectangle(int w, int h) : width(w), height(h) {} | Rectangle::Rectangle(int w, int h) : width(w), height(h) {} |
</code> | </code> |
| |
Τελικά η κλάση Rectangle μπορεί να γραφεί ως εξής: | Ο παραπάνω τρόπος γραφής ονομάζεται στη βιβλιογραφία __member initilization list__. Τελικά η κλάση Rectangle μπορεί να γραφεί με χρήση //member initilization list// όπως παρακάτω: |
| |
<code cpp Rectangle.hpp> | <code cpp Rectangle.hpp> |
| |
<code> | <code> |
Cuboid::Cuboid(Rectangle r, int l) : rect(r), length(l) { } | Cuboid::Cuboid(Rectangle r, int l) : rect(r), length(l) { } |
Cuboid::Cuboid(int w, int h, int l) : rect(w,h), length(l) { } | Cuboid::Cuboid(int w, int h, int l) : rect(w,h), length(l) { } |
</code> | </code> |
| |
Στην 1η περίπτωση γίνεται ανάθεση του αντικειμένου //r// στο πεδίο //rect//. Στην 2η περίπτωση καλείται ο κατασκευαστής της κλάσης //Rectangle// με ορίσματα //(w,h)//. | Στον πρώτο κατασκευαστή με τα δύο ορίσματα γίνεται ανάθεση του αντικειμένου //r// στο πεδίο //rect//, αντιγράφοντας την τιμή κάθε πεδίου της παραμέτρου //r// στο πεδίιο //rect//. Στον 2ο κατασκευαστή με τα τρία ορίσματα καλείται ο κατασκευαστής της κλάσης //Rectangle// με ορίσματα //(w,h)//. |
| |
Η ανάθεση ''rect = r;'' δεν είναι προφανής. Έχοντας δύο αντικείμενα τύπου Rectangle το ''rect'' και το ''r'', η εντολή ανάθεσης αντιγράφει τα περιεχόμενα του ''r'' στο ''rect'' πεδίο προς πεδίο. | |
| |
| |