cpp:exception
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
cpp:exception [2019/05/06 07:13] – [Διαχείριση Εξαιρέσεων] gthanos | cpp:exception [2019/05/06 07:17] – [Κληρονομικότητα εξαιρέσεων] gthanos | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Διαχείριση Εξαιρέσεων ====== | + | ====== |
Ας εξετάσουμε την κλάση **Vector** που είδαμε στην ενότητα της υπερφόρτωση τελεστών. Ο προσδιοριστής //nothrow// σε συνδυασμό με τον τελεστή **new** μας υποχρεώνει να ελέγξουμε την επιστρεφόμενη τιμή του τελεστή **new** για να δούμε έαν έχει αποτύχει η διαδικασία δέσμευσης μνήμης ή όχι και στην περίπτωση που έχουμε αποτυχία τερματίζουμε το πρόγραμμα. | Ας εξετάσουμε την κλάση **Vector** που είδαμε στην ενότητα της υπερφόρτωση τελεστών. Ο προσδιοριστής //nothrow// σε συνδυασμό με τον τελεστή **new** μας υποχρεώνει να ελέγξουμε την επιστρεφόμενη τιμή του τελεστή **new** για να δούμε έαν έχει αποτύχει η διαδικασία δέσμευσης μνήμης ή όχι και στην περίπτωση που έχουμε αποτυχία τερματίζουμε το πρόγραμμα. | ||
Line 164: | Line 164: | ||
break; | break; | ||
case 4: | case 4: | ||
- | throw string(" | + | throw string(" |
break; | break; | ||
case 5: | case 5: | ||
Line 170: | Line 170: | ||
break; | break; | ||
default: | default: | ||
- | c = -10; throw c; // throw a character | + | c = -10; throw c; // throw a character |
break; | break; | ||
} | } | ||
Line 204: | Line 204: | ||
</ | </ | ||
- | ===== Κληρονομικότητα εξαιρέσεων ===== | ||
- | |||
- | Ας υποθέσουμε ότι έχουμε τη σχέση κληρονομικότητας μεταξύ των κλάσεων **BaseException** και **DerivedException**, | ||
- | |||
- | <code cpp BaseException.h> | ||
- | using namespace std; | ||
- | |||
- | class BaseException: | ||
- | protected: | ||
- | int a; | ||
- | public: | ||
- | BaseException(int a) { this->a = a; } | ||
- | const char* what() const throw() { | ||
- | //char s[64]; | ||
- | char *s = new char [64]; | ||
- | sprintf(s, " | ||
- | return s; | ||
- | } | ||
- | }; | ||
- | </ | ||
- | |||
- | <code cpp DerivedException.h> | ||
- | #include " | ||
- | using namespace std; | ||
- | |||
- | class DerivedException: | ||
- | int b; | ||
- | public: | ||
- | DerivedException(int a, int b): BaseException(a) { this->b = b; } | ||
- | const char* what() const throw() { | ||
- | char *s = new char [64]; | ||
- | sprintf(s, " | ||
- | return s; | ||
- | } | ||
- | }; | ||
- | </ | ||
- | |||
- | <code cpp ExceptionUse.cpp> | ||
- | #include < | ||
- | #include " | ||
- | using namespace std; | ||
- | |||
- | int main() { | ||
- | try { | ||
- | int option; | ||
- | cout << "Enter option (1-2): "; | ||
- | cin >> option; | ||
- | BaseException bex(-2); | ||
- | DerivedException dex(4,5); | ||
- | switch(option) { | ||
- | case 1: | ||
- | throw bex; | ||
- | break; | ||
- | case 2: | ||
- | throw dex; | ||
- | break; | ||
- | } | ||
- | } catch(BaseException ex) { | ||
- | cout << ex.what(); | ||
- | } catch(DerivedException ex) { | ||
- | cout << ex.what(); | ||
- | } | ||
- | return 0; | ||
- | } | ||
- | </ | ||
- | |||
- | O παραπάνω κώδικας παράγει το παρακάτω //warning// κατά τη μεταγλώττιση: | ||
- | < | ||
- | ExceptionUse.cpp: | ||
- | } catch(DerivedException &ex) { | ||
- | ^ | ||
- | ExceptionUse.cpp: | ||
- | } catch(BaseException &ex) { | ||
- | ^ | ||
- | </ | ||
- | |||
- | το οποίο εν συντομία λέει ότι ένα exception τύπου // | ||
- | |||
- | Εκτελέστε όμως τον παραπάνω κώδικα (παρά το warning) δίνοντας ορίσμα τους αριθμούς 1 και 2. Το αποτέλεσμα είναι το εξής: | ||
- | < | ||
- | gthanos@gthanos-DESKTOP: | ||
- | Enter option (1-2): 1 | ||
- | BaseException, | ||
- | gthanos@gthanos-DESKTOP: | ||
- | Enter option (1-2): 2 | ||
- | BaseException, | ||
- | </ | ||
- | |||
- | Παρατηρήστε ότι ενώ στην 2η περίπτωση παράγεται ένα // | ||
- | |||
- | Η απάντηση στο παραπάνω ερώτημα είναι ότι αν και παράγεται ένα αντικείμενο τύπου // | ||
- | |||
- | Ο τρόπος για να δουλέψει σωστά ο παραπάνω κώδικας είναι μέσα στο //catch block// να μην περάσουμε το αντικείμενο γιατί δημιουργείται αντίγραφο, | ||
- | |||
- | <code cpp ExceptionUse.cpp> | ||
- | #include < | ||
- | #include " | ||
- | using namespace std; | ||
- | |||
- | int main() { | ||
- | try { | ||
- | int option; | ||
- | cout << "Enter option (1-2): "; | ||
- | cin >> option; | ||
- | BaseException bex(-2); | ||
- | DerivedException dex(4,5); | ||
- | switch(option) { | ||
- | case 1: | ||
- | throw bex; | ||
- | break; | ||
- | case 2: | ||
- | throw dex; | ||
- | break; | ||
- | } | ||
- | } catch(BaseException &ex) { | ||
- | cout << ex.what(); | ||
- | } catch(DerivedException &ex) { | ||
- | cout << ex.what(); | ||
- | } | ||
- | return 0; | ||
- | } | ||
- | </ | ||
- | |||
- | Πλέον το αποτέλεσμα της εκτέλεσης είναι το αναμενόμενο | ||
- | < | ||
- | gthanos@gthanos-DESKTOP: | ||
- | Enter option (1-2): 1 | ||
- | BaseException, | ||
- | gthanos@gthanos-DESKTOP: | ||
- | Enter option (1-2): 2 | ||
- | DerivedException, | ||
- | </ | ||
- | |||
- | <WRAP tip 80% center round> | ||
- | Το πιάσιμο μιας εξαίρεσης με χρήση αναφοράς για αντικείμενα σύνθετου τύπου (όχι char, int, long, double κλπ), διότι //α)// αποφεύγουμε την αντιγραφή του αντικειμένου μέσα στο //catch block// (πιο γρήγορος κώδικας) και //β)// αποφεύγουμε την " | ||
- | </ | ||
- | |||
- | <WRAP tip 80% center round> | ||
- | Είναι προφανές ότι η σειρά των //catch blocks// θα έπρεπε να είναι η αντίστροφη (πρώτα το //catch block// για την αναφορά τύπου // | ||
- | </ | ||
===== Stack Unwinding ===== | ===== Stack Unwinding ===== |
cpp/exception.txt · Last modified: 2023/05/15 14:01 by gthanos