User Tools

Site Tools


cpp:function_try_blocks

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:function_try_blocks [2019/05/06 19:43] – [Exception που συμβαίνουν στον κατασκευαστή της προγόνου κλάσης] gthanoscpp:function_try_blocks [2022/05/23 06:05] (current) – [Εξαιρέσεις που παράγονται στον κατασκευαστή] gthanos
Line 32: Line 32:
  
 Name& Name::operator=(const Name& a) { Name& Name::operator=(const Name& a) {
 +  cout << "--- Operator= ---\n";
   if(name != nullptr)    if(name != nullptr) 
     free(name);     free(name);
Line 41: Line 42:
 και την κλάση //Person// η οποία περιγράφει έναν άνθρωπο. Η κλάση διαθέτει τα εξής δύο πεδία: και την κλάση //Person// η οποία περιγράφει έναν άνθρωπο. Η κλάση διαθέτει τα εξής δύο πεδία:
 <code cpp>  <code cpp> 
-  Name* firstname;  // pointer  +  Name* firstname;  // pointer to Name 
-  Name lastname;+  Name lastname;    // Name
 </code> </code>
  
-Επιπλέον ο κατασκευαστή της κλάση Person παράγει ένα //exception// τύπου //BadName//. Η κλάσεις //BadName// και //Person// περιγράφονται παρακάτω: +Επιπλέον ο κατασκευαστή της κλάση Person παράγει ένα //exception// τύπου //BadName//. Η κλάσεις //Person// και //BadName// περιγράφονται παρακάτω:
- +
-<code cpp BadName.hpp> +
-class BadName : public std::exception { +
-public: +
-  const char* what() { +
-    return "BadName"; +
-  } +
-}; +
-</code>+
  
 <code cpp Person.hpp> <code cpp Person.hpp>
Line 81: Line 73:
   delete firstname;   delete firstname;
 } }
 +</code>
 +
 +<code cpp BadName.hpp>
 +class BadName : public std::exception {
 +public:
 +  const char* what() {
 +    return "BadName";
 +  }
 +};
 </code> </code>
  
 Εάν μεταγλωττίσουμε και εκτελέσουμε την παρακάτω συνάρτηση //main// ο κώδικας εκτυπώνει τα εξής: Εάν μεταγλωττίσουμε και εκτελέσουμε την παρακάτω συνάρτηση //main// ο κώδικας εκτυπώνει τα εξής:
-<code cpp main.cpp>+<code cpp CreatePerson.cpp>
 #include <iostream> #include <iostream>
 using namespace std; using namespace std;
Line 104: Line 105:
 Name constructor: John Name constructor: John
 Name constructor: Snow Name constructor: Snow
 +--- Operator= ---
 Name destructor: Snow Name destructor: Snow
 Name destructor: Snow Name destructor: Snow
-Occured: BadName+Exception occured: BadName
 </code> </code>
  
-Από τις εκτυπώσεις, παρατηρούμε ότι καταστρέφεται το αντικείμενο //lastname//, αλλά όχι και το αντικείμενο //firstname//. Ο λόγος είναι ότι δημιουργηθεί ένα //exception// στον κατασκευαστή, __δεν καλείται ποτέ ο καταστροφέας της κλάσης__. Καταστρέφονται αυτόματα όλα τα αντικείμενα που έχουν δεσμευτεί στο //stack//, και λαμβάνει χώρα η διαδικασία του //stack unwinding// που είδαμε σε προηγούμενη παράγραφο.+Από τις εκτυπώσεις, παρατηρούμε ότι καταστρέφεται το αντικείμενο //lastname//, αλλά όχι και το αντικείμενο //firstname//. Ο λόγος είναι ότι δημιουργηθεί ένα //exception// στον κατασκευαστή, __δεν καλείται ποτέ ο καταστροφέας της κλάσης__. Καταστρέφονται αυτόματα όλα τα αντικείμενα που έχουν δεσμευτεί στο //stack//, και λαμβάνει χώρα η διαδικασία του //[[cpp:stack_unwinding|stack unwinding]]//.
  
-Ως εκ τούτου, δεν καταστρέφονται τα αντικείμενα που είναι δεσμευμένα στο //heap// και γενικότερα //resources// που περιμένουμε να απελευθερωθούν στον καταστροφέα της κλάσης.+Ως εκ τούτου, δεν καταστρέφονται τα αντικείμενα που είναι δεσμευμένα στο //heap// και γενικότερα τα //resources// που περιμένουμε να απελευθερωθούν στον καταστροφέα της κλάσης.
  
 <WRAP tip 80% center round> <WRAP tip 80% center round>
-Ο λόγος που εκτυπώνεται 2 φορές το μήνυμα **"Name destructor: Snow"**, είναι διότι δημιουργούνται δύο αντικείμενα τύπου Name, ένα κατά την αρχικοποίηση του αντικειμένου //Person// και ένα στον κατασκευαστή της κλάσης στη γραμμή ''lastname = Name(last);''+Ο λόγος που εκτυπώνεται 2 φορές το μήνυμα **"Name destructor: Snow"**, είναι διότι δημιουργούνται δύο αντικείμενα τύπου Name, ένα κατά την αρχικοποίηση του αντικειμένου //Person// (με τη βοήθεια του //default constructor//)και ένα στον κατασκευαστή της κλάσης στη γραμμή ''lastname = Name(last);''
 </WRAP> </WRAP>
  
Line 130: Line 132:
 } }
 catch(BadName& ex) { catch(BadName& ex) {
-  cout << "--> firstname deleted!" << endl;+  cout << "\n--> firstname deleted!" << endl;
   delete firstname;   delete firstname;
 } }
Line 142: Line 144:
 Name constructor: John Name constructor: John
 Name constructor: Snow Name constructor: Snow
 +--- Operator= ---
 Name destructor: Snow Name destructor: Snow
 Name destructor: Snow Name destructor: Snow
 +
 --> firstname deleted! --> firstname deleted!
 Name destructor: John Name destructor: John
-Occured: BadName+Exception occured: BadName
 </code> </code>
  
-<WRAP tip 80% center round> +<WRAP important 80% center round> 
-Παρατηρήστε ότι αν και εκτελείται ο κώδικας μέσα στο //catch block//, η εξαίρεση "μεταφέρεται" και στη συνάρτηση //main///. Ο λόγος είναι ότι η εξαίρεση, αναπαράγεται αυτόματα στο τέλος του //catch block//. Ο μόνος τρόπος να το αποφύγετε αυτό είναι να κάνετε //throw// μία νέα εξαίρεση, διαφορετικού τύπου.+Παρατηρήστε ότι αν και εκτελείται ο κώδικας μέσα στο //catch block//, η εξαίρεση "μεταφέρεται" και στη συνάρτηση //main//. Ο λόγος είναι ότι η εξαίρεση, **αναπαράγεται αυτόματα** στο τέλος του //catch block//. Ο μόνος τρόπος να το αποφύγετε αυτό είναι να κάνετε //throw// μία νέα εξαίρεση, διαφορετικού τύπου.
 </WRAP> </WRAP>
  
Line 169: Line 173:
 </code> </code>
  
-Εάν επιθυμούμε να "πιάσουμε" την εξαίρεση εντός του κατασκευαστή της κλάσης //Student// θα πρέπει να κρατήσουμε τον κατασκευαστή της κλάσης //Person// στην αρχική του μορφή και να ξαναγράψουμε τον κατασκευαστή: +Εάν επιθυμούμε να "πιάσουμε" την εξαίρεση εντός του κατασκευαστή της κλάσης //Student// και όχι εντός της //Person//, θα πρέπει να κρατήσουμε τον κατασκευαστή της κλάσης //Person// στην αρχική του μορφή (πριν την τελευταία αλλαγή) και να ξαναγράψουμε τον κατασκευαστή της κλάσης //Student// ως εξής: 
-<code cpp>+ 
 +<code cpp Student.hpp>
 class Student: public Person { class Student: public Person {
   int aem;   int aem;
Line 186: Line 191:
 </code> </code>
  
-Η παραπάνω σύνταξη επιτρέπει να πιάσουμε το exception που συμβαίνει στον κατασκευαστή της προγόνου κλάσης. Και εδώ το //exception// θα αναπαραχθεί σύμφωνα με τους κανόνες που ίσχυσαν και στο προηγούμενο παράδειγμα.+Η παραπάνω σύνταξη επιτρέπει να πιάσουμε το exception που συμβαίνει στον κατασκευαστή της προγόνου κλάσης. Και εδώ το //exception// θα αναπαραχθεί σύμφωνα με τους κανόνες που ίσχυσαν και στο προηγούμενο παράδειγμα.  
 + 
 +<WRAP tip 80% center round> 
 +Παρατηρήστε ότι δεν εκτυπώνεται ποτέ το μήνυμα **"Student constructor"** του κατασκευαστή. Γιατί? 
 +</WRAP> 
 + 
 +Η μέθοδος //main// δίνεται παρακάτω: 
 + 
 +<code cpp main.cpp> 
 +#include <iostream> 
 +using namespace std; 
 + 
 +#include "Person.hpp" 
 +#include "Student.hpp" 
 + 
 +int main() { 
 +  try { 
 +    Student johnSnow("John", "Snow", 1234); 
 +  } catch(BadName& a) { 
 +    cout << "Exception occured: " << a.what() << endl; 
 +  } 
 +
 +</code>
  
cpp/function_try_blocks.1557171784.txt.gz · Last modified: 2019/05/06 18:43 (external edit)