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/18 13:45] – [Κληρονομικότητα] gthanos | cpp:exception [2018/05/19 03:29] – [Κληρονομικότητα] gthanos | ||
---|---|---|---|
Line 199: | Line 199: | ||
<code cpp BaseException.h> | <code cpp BaseException.h> | ||
+ | using namespace std; | ||
+ | |||
class BaseException: | class BaseException: | ||
protected: | protected: | ||
Line 205: | Line 207: | ||
BaseException(int a) { this->a = a; } | BaseException(int a) { this->a = a; } | ||
const char* what() const throw() { | const char* what() const throw() { | ||
- | char s[64]; | + | |
- | sprintf(s, " | + | char *s = new char [64]; |
+ | sprintf(s, " | ||
return s; | return s; | ||
} | } | ||
Line 214: | Line 217: | ||
<code cpp DerivedException.h> | <code cpp DerivedException.h> | ||
#include " | #include " | ||
+ | using namespace std; | ||
+ | |||
class DerivedException: | class DerivedException: | ||
int b; | int b; | ||
public: | public: | ||
- | DerivedException(int a, int b): Base(a) { this->b = b; } | + | DerivedException(int a, int b): BaseException(a) { this->b = b; } |
const char* what() const throw() { | const char* what() const throw() { | ||
- | char s[64]; | + | char *s = new char [64]; |
- | sprintf(s, " | + | sprintf(s, " |
return s; | return s; | ||
} | } | ||
Line 228: | Line 233: | ||
<code cpp ExceptionUse.cpp> | <code cpp ExceptionUse.cpp> | ||
#include < | #include < | ||
+ | #include " | ||
using namespace std; | using namespace std; | ||
int main() { | int main() { | ||
try { | 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) { | } catch(BaseException ex) { | ||
cout << ex.what(); | cout << ex.what(); | ||
Line 240: | Line 259: | ||
} | } | ||
</ | </ | ||
+ | |||
+ | 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// (πιο γρήγορος κώδικας) και //β)// αποφεύγουμε την " | ||
+ | </ | ||
+ | |||
+ | ===== 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; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
cpp/exception.txt · Last modified: 2023/05/15 14:01 by gthanos