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 [2018/05/21 02:00] – [Ένα 2ο παράδειγμα] gthanos | cpp:exception [2019/05/06 07:19] – [Stack Unwinding] gthanos | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Διαχείριση Εξαιρέσεων ====== | + | ====== |
- | Ας εξετάσουμε την κλάση **Vector** που είδαμε στην υπερφόρτωση | + | Ας εξετάσουμε την κλάση **Vector** που είδαμε στην |
<code cpp Vector.cpp> | <code cpp Vector.cpp> | ||
Line 43: | Line 43: | ||
</ | </ | ||
- | Αν και η παραπάνω διαδικασία δεν είναι λανθασμένη, | + | Αν και η παραπάνω διαδικασία δεν είναι λανθασμένη, |
<code cpp VectorUse.cpp> | <code cpp VectorUse.cpp> | ||
Line 58: | Line 58: | ||
</ | </ | ||
- | Η παραγωγή ενός exception μπορεί να επιλύσει πιο αποτελεσματικά το παραπάνω πρόβλημα διότι | + | Η παραγωγή ενός |
<code cpp Vector.cpp> | <code cpp Vector.cpp> | ||
Line 78: | Line 78: | ||
Vector:: | Vector:: | ||
size = length; | size = length; | ||
- | array = new (nothrow) | + | array = new int[size]; |
for(int i=0; i<size; i++) | for(int i=0; i<size; i++) | ||
array[i] = 0; | array[i] = 0; | ||
Line 117: | Line 117: | ||
<WRAP tip 80% center round> | <WRAP tip 80% center round> | ||
- | Αν και στο παραπάνω απλό παράδειγμα είναι προφανές ότι είναι πιο απλό να ελέγξει κανείς το μέγεθος της παραμέτρου size πριν καλέσει τον κατασκευαστή, κάτι τέτοιο | + | Στο παραπάνω απλό παράδειγμα είναι προφανές ότι είναι πιο απλό να ελέγξει κανείς το μέγεθος της παραμέτρου |
</ | </ | ||
===== Τύποι παραγόμενων εξαιρέσεων ===== | ===== Τύποι παραγόμενων εξαιρέσεων ===== | ||
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-> | + | |
- | 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-> | + | |
- | 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> | + | |
- | Το πιάσιμο μιας εξαίρεσης με χρήση αναφοράς | + | |
- | </ | + | |
- | + | ||
- | <WRAP tip 80% center round> | + | |
- | Είναι προφανές ότι η σειρά των //catch blocks// θα έπρεπε να είναι | + | |
- | </ | + | |
- | ===== Stack Unwinding ===== | + | |
- | + | ||
- | Κατά την δημιουργία ενός // | + | |
- | + | ||
- | <code cpp StackUnwinding.cpp> | + | |
- | #include < | + | |
- | // called by FFF() | + | |
- | void FFFF() { | + | |
- | std::cout << "Start FFFF\n"; | + | |
- | std::cout << "FFFF throwing int literal exception\n"; | + | |
- | throw 100; | + | |
- | std::cout << "End FFFF\n"; | + | |
- | + | ||
- | } | + | |
- | // called by FF() | + | |
- | void FFF() { | + | |
- | std::cout << "Start FFF\n"; | + | |
- | FFFF(); | + | |
- | std::cout << "End FFF\n"; | + | |
- | } | + | |
- | // called by F() | + | |
- | void FF() { | + | |
- | std::cout << "Start FF\n"; | + | |
- | try { | + | |
- | FFF(); | + | |
- | } catch(char) { | + | |
- | std::cerr << "FF caught double exception\n"; | + | |
- | } | + | |
- | std::cout << "End FF\n"; | + | |
- | } | + | |
- | // called by main() | + | |
- | void F() { | + | |
- | std::cout << "Start F\n"; | + | |
- | try { | + | |
- | FF(); | + | |
- | } catch (int) { | + | |
- | | + | |
- | } catch (char) { | + | |
- | | + | |
- | } | + | |
- | std::cout << "End F\n"; | + | |
- | } | + | |
- | + | ||
- | int main() { | + | |
- | std::cout << "Start main\n"; | + | |
- | try { | + | |
- | F(); | + | |
- | } catch (int) { | + | |
- | std::cerr << "main caught int exception\n"; | + | |
- | } | + | |
- | std::cout << "End main\n"; | + | |
- | return 0; | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Το αποτέλεσμα που εκτυπώνεται στην οθόνη είναι το εξής: | + | |
- | < | + | |
- | Start main | + | |
- | Start F | + | |
- | Start FF | + | |
- | Start FFF | + | |
- | Start FFFF | + | |
- | FFFF throwing int literal exception | + | |
- | F caught int exception | + | |
- | End F | + | |
- | End main | + | |
- | </ | + | |
- | + | ||
- | H εξέλιξη του //program stack// στο παρακάτω πρόγραμμα δίνεται στο παρακάτω διάγραμμα. Παρατηρήστε ότι το exception παράγεται στη συνάρτηση **FFFF()**, αλλά " | + | |
- | + | ||
- | {{ : | + | |
- | + | ||
- | ===== Διαχείριση μίας εξαίρεσης και παραγωγή μίας νέας εξαίρεσης κατά την διαχείριση | + | |
Κάποιες φορές είναι επιθυμητό να διαχειριστούμε μία εξαίρεση προκειμένου να κλείσουμε κάποιο // | Κάποιες φορές είναι επιθυμητό να διαχειριστούμε μία εξαίρεση προκειμένου να κλείσουμε κάποιο // | ||
Line 551: | Line 341: | ||
cerr << " | cerr << " | ||
in.close(); | in.close(); | ||
- | throw ex; // rethrows the same exception object | + | throw; |
} | } | ||
</ | </ | ||
Line 563: | Line 353: | ||
Τους παραπάνω ορισμούς είναι δυνατόν να τους συναντήσετε στις // | Τους παραπάνω ορισμούς είναι δυνατόν να τους συναντήσετε στις // | ||
+ | /* | ||
===== Function try blocks ===== | ===== Function try blocks ===== | ||
- | + | */ | |
- | ===== Η κλάση std:: | + | |
cpp/exception.txt · Last modified: 2023/05/15 14:01 by gthanos