User Tools

Site Tools


cpp:constructors_destructors

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
cpp:constructors_destructors [2020/04/08 08:04] gthanoscpp:constructors_destructors [Unknown date] (current) – external edit (Unknown date) 127.0.0.1
Line 1: Line 1:
 ====== Κατασκευαστές και καταστροφείς της κλάσης ====== ====== Κατασκευαστές και καταστροφείς της κλάσης ======
  
-Στο προηγούμενο παράδειγμα της κλάσης //Rectangle// δεν δηλώθηκε κάποιος κατασκευαστής. Ο κατασκευαστής της κλάσης είναι μέθοδος που έχει το όνομα της κλάσης και δεν έχει επιστρεφόμενο τύπο. Ο ρόλος του κατασκευαστή της κλάσης είναι να αρχικοποιήσει τις τιμές των πεδίων της κλάσης. Για την κλάση //Rectangle//, παρακάτω δηλώνεται ο κατασκευαστής ''Rectangle(int w, int h)''.+Στο προηγούμενο παράδειγμα της κλάσης //Rectangle// δεν δηλώθηκε κάποιος κατασκευαστής. Ο κατασκευαστής της κλάσης είναι μέθοδος που έχει το όνομα της κλάσης και δεν έχει επιστρεφόμενο τύπο. Ο ρόλος του κατασκευαστή της κλάσης είναι να αρχικοποιήσει τις τιμές των πεδίων της κλάσης. Σημειώστε, ότι ο κατασκευαστής της κλάσης στη C++ δεν δεσμεύει χώρο στη μνήμη, όπως συμβαίνει στη Java. Για την κλάση //Rectangle//, παρακάτω δηλώνεται ο κατασκευαστής ''Rectangle(int w, int h)''.
  
 <code cpp Rectangle.hpp> <code cpp Rectangle.hpp>
Line 38: Line 38:
 </code> </code>
  
-<WRAP center round tip 80%>+<WRAP center round info 80%>
 Σε αναλογία με τις μεθόδους ο κατασκευαστής μπορεί να οριστεί εντός της κλάσης, όπως παρακάτω. Η δήλωση εντός της κλάσης συνεπάγεται τη δήλωση από τον προγραμματιστή του κατασκευαστή ως //inline//. Σε αναλογία με τις μεθόδους ο κατασκευαστής μπορεί να οριστεί εντός της κλάσης, όπως παρακάτω. Η δήλωση εντός της κλάσης συνεπάγεται τη δήλωση από τον προγραμματιστή του κατασκευαστή ως //inline//.
 <code c++ Rectangle.cpp> <code c++ Rectangle.cpp>
Line 56: Line 56:
 Εάν δεν οριστεί κανένας κατασκευαστής σε μία κλάση τότε για την κλάση ορίζεται από τον μεταγλωττιστή ο //default// κατασκευαστής. Ο κατασκευαστής αυτός δεν έχει ορίσματα. Τα πεδία της κλάσης αρχικοποιούνται ως εξής: Εάν δεν οριστεί κανένας κατασκευαστής σε μία κλάση τότε για την κλάση ορίζεται από τον μεταγλωττιστή ο //default// κατασκευαστής. Ο κατασκευαστής αυτός δεν έχει ορίσματα. Τα πεδία της κλάσης αρχικοποιούνται ως εξής:
   - για πεδία που έχουν βασικού τύπους (int, double, char κλπ) οι τιμές είναι τυχαίες.   - για πεδία που έχουν βασικού τύπους (int, double, char κλπ) οι τιμές είναι τυχαίες.
-  - για πεδία αναφορικού τύπου καλείται ο default κατασκευαστής της εκάστοτε κλάσης.+  - για πεδία που περιγράφονται από κλάσεις καλείται ο //default// κατασκευαστής της εκάστοτε κλάσης.
  
-Εάν έχετε δηλώσει τουλάχιστον ένα κατασκευαστή που δεν είναι ο //default// κατασκευαστής χωρίς παραμέτρους τότε ο μεταγλωττιστής δεν κατασκευάζει αυτόματα τον //default// κατασκευαστή. Σε περίπτωση που ο //default// κατασκευαστής απαιτείται λαμβάνετε μήνυμα λάθους από τον μεταγλωττιστή.+Εάν έχετε δηλώσει τουλάχιστον ένα κατασκευαστή που δεν είναι ο //default// κατασκευαστής χωρίς παραμέτρους τότε ο //compiler// δεν κατασκευάζει αυτόματα τον //default// κατασκευαστή. Σε περίπτωση που ο //default// κατασκευαστής δεν δημιουργηθεί αυτόματα από τον //compiler//, λαμβάνετε μήνυμα λάθους κατά τη μεταγλώττιση.
  
 ===== Υπερφόρτωση κατασκευαστών ===== ===== Υπερφόρτωση κατασκευαστών =====
Line 133: Line 133:
 </code> </code>
  
-Ο παραπάνω τρόπος αρχικοποίησης μπορεί να επεκταθεί και να χρησιμοποιηθεί για την κλήση κατασκευαστών των πεδίων της κλάσης, όταν αυτά είναι αναφορικού τύπου. Για παράδειγμα, δείτε παρακάτω την κλάση //Cuboid// η οποία διαθέτει ένα πεδίο της κλάσης //Rectangle//+Τελικά η κλάση Rectangle μπορεί να γραφεί ως εξής:
  
-<code cpp Cuboid.cpp>+<code cpp Rectangle.hpp>
 #include <iostream> #include <iostream>
 +#include <cstdlib>
 +#include <ctime>
 using namespace std; using namespace std;
  
-#include "Rectangle.cpp"+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(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; 
 +
 + 
 +void Rectangle::setWidth(int w) { width = w; } 
 +void Rectangle::setHeight(int h) { height = h; } 
 +int Rectangle::getWidth() const { return width; } 
 +int Rectangle::getHeight() const { return height; } 
 +</code> 
 + 
 +===== Κλήση ενός κατασκευαστή μέσα από άλλο κατασκευαστή ===== 
 + 
 +Συχνά μπορεί να θέλουμε να καλέσουμε μέσα από ένα κατασκευαστή έναν άλλο κατασκευαστή. Μπορείτε να το κάνετε αυτό χρησιμοποιώντας ως οποιαδήποτε άλλη μέθοδο. Στο προηγούμενο παράδειγμα, ο κατασκευαστής με τη μία παράμετρο καλεί εσωτερικά τον κατασκευαστή με τις δύο παραμέτρους ως εξής: 
 + 
 +<code cpp> 
 +Rectangle::Rectangle(int s) { 
 +  Rectangle(s,s); 
 +
 +</code> 
 + 
 +O ίδιος κώδικας με χρήση //initialization list// μπορεί να γραφεί ως εξής: 
 + 
 +<code cpp> 
 +Rectangle::Rectangle(int s) : Rectangle(s,s) { 
 +
 +</code> 
 + 
 +===== Αρχικοποίηση αντικειμένων που περιέχουν πεδία που περιγράφονται από κλάσεις ===== 
 + 
 +Στην προηγούμενη ενότητα είδαμε την κλάση Cuboid που περιγράφει την κλάση του κυβοειδούς και περιέχει ένα πεδίο τύπου Rectangle. Εδώ θα δούμε πως μπορούμε να ορίσουμε ένα ή περισσότερους κατασκευαστές για τη συγκεκριμένη κλάση. 
 + 
 +<code cpp Cuboid.hpp> 
 +#include <iostream> 
 +using namespace std; 
 + 
 +#include "Rectangle.hpp"
  
 class Cuboid { class Cuboid {
Line 146: Line 203:
     Rectangle rect;     Rectangle rect;
   public:   public:
-    Cuboid(Rectangle r, int l); 
     Cuboid(int w, int h, int l);     Cuboid(int w, int h, int l);
-    void setRectangle(Rectangle r) {rect = r;} +    Cuboid(Rectangle r, int l); 
-    Rectangle getRectangle() {return rect;} +     
-    void setLength(int l) { length = l} +    void setRectangle(Rectangle r); 
-    int getLength() const { return length}+    Rectangle getRectangle() const
 +    void setLength(int l); 
 +    int getLength() const;
     int volume();     int volume();
 }; };
 +</code>
  
-Cuboid::Cuboid(Rectangle r, int l) : rect(r), length(l) { } +<code cpp Cuboid.cpp> 
-Cuboid::Cuboid(int w, int h, int l) : rect(w,h), length(l) { }+#include "Cuboid.hpp"
  
-int Cuboid::volume() { +Cuboid::Cuboid(int w, int h, int l 
-  return length * rect.getWidth() rect.getHeight();+  rect.setWidth(w)
 +  rect.setHeight(h)
 +  length = l;
 } }
-</code> 
  
-<code cpp CuboidUsage.cpp> +Cuboid::Cuboid(Rectangle r, int l) { 
-#include "Cuboid.cpp"+   rect = r; 
 +   length = l; 
 +}
  
-int main () { +void Cuboid::setRectangle(Rectangle r) {rect = r;} 
-  Rectangle rect(5,6)+Rectangle Cuboid::getRectangle() const {return rect;} 
-  Cuboid cuboid1(rect, 10); +void Cuboid::setLength(int l{ length = l} 
-  cout << "volume" << cuboid1.volume() << endl+int Cuboid::getLength() const { return length} 
-  Cuboid cuboid2(2,3,4); + 
-  cout << "volume" << cuboid2.volume() << endl; +int Cuboid::volume() { 
-  return 0;+  return length * rect.getWidth() * rect.getHeight();
 } }
 </code> </code>
  
-Παρατηρήστε πως ορίζονται οι κατασκευαστές της κλάσης //Cuboid// με χρήση //member initialization list//. +Οι παραπάνω δύο κατασκευαστές με χρήση member initialιzation list μπορούν να γραφούν ως εξής: 
 <code> <code>
 Cuboid::Cuboid(Rectangle r, int l) : rect(r), length(l) { } Cuboid::Cuboid(Rectangle r, int l) : rect(r), length(l) { }
Line 183: Line 246:
  
 Στην 1η περίπτωση γίνεται ανάθεση του αντικειμένου //r// στο πεδίο //rect//. Στην 2η περίπτωση καλείται ο κατασκευαστής της κλάσης //Rectangle// με ορίσματα //(w,h)//. Στην 1η περίπτωση γίνεται ανάθεση του αντικειμένου //r// στο πεδίο //rect//. Στην 2η περίπτωση καλείται ο κατασκευαστής της κλάσης //Rectangle// με ορίσματα //(w,h)//.
 +
 +Η ανάθεση ''rect = r;'' δεν είναι προφανής. Έχοντας δύο αντικείμενα τύπου Rectangle το ''rect'' και το ''r'', η εντολή ανάθεσης αντιγράφει τα περιεχόμενα του ''r'' στο ''rect'' πεδίο προς πεδίο.
  
 ===== Καταστροφέας της κλάσης ===== ===== Καταστροφέας της κλάσης =====
cpp/constructors_destructors.1586333070.txt.gz · Last modified: 2020/04/08 07:04 (external edit)