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:17] – [Κληρονομικότητα εξαιρέσεων] gthanos | cpp:exception [2021/05/07 14:42] – [Δημιουργία και Διαχείριση Εξαιρέσεων] gthanos | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Δημιουργία | + | ====== Δημιουργία |
Ας εξετάσουμε την κλάση **Vector** που είδαμε στην ενότητα της υπερφόρτωση τελεστών. Ο προσδιοριστής //nothrow// σε συνδυασμό με τον τελεστή **new** μας υποχρεώνει να ελέγξουμε την επιστρεφόμενη τιμή του τελεστή **new** για να δούμε έαν έχει αποτύχει η διαδικασία δέσμευσης μνήμης ή όχι και στην περίπτωση που έχουμε αποτυχία τερματίζουμε το πρόγραμμα. | Ας εξετάσουμε την κλάση **Vector** που είδαμε στην ενότητα της υπερφόρτωση τελεστών. Ο προσδιοριστής //nothrow// σε συνδυασμό με τον τελεστή **new** μας υποχρεώνει να ελέγξουμε την επιστρεφόμενη τιμή του τελεστή **new** για να δούμε έαν έχει αποτύχει η διαδικασία δέσμευσης μνήμης ή όχι και στην περίπτωση που έχουμε αποτυχία τερματίζουμε το πρόγραμμα. | ||
Line 35: | Line 35: | ||
int & | int & | ||
- | if(pos>=length()) { | + | if(pos>=size) { |
cerr << " | cerr << " | ||
| | ||
Line 107: | Line 107: | ||
Vector v(size); | Vector v(size); | ||
} catch(std:: | } catch(std:: | ||
- | cout << " | + | |
- | continue; | + | |
+ | continue; | ||
+ | } | ||
+ | exit(-1); | ||
} | } | ||
for(int i=0; i<size; i++) | for(int i=0; i<size; i++) | ||
Line 117: | Line 120: | ||
<WRAP tip 80% center round> | <WRAP tip 80% center round> | ||
- | Στο παραπάνω απλό παράδειγμα είναι προφανές ότι είναι πιο απλό να ελέγξει κανείς το μέγεθος της παραμέτρου //size// πριν καλέσει τον κατασκευαστή. Σε αυτή την περίπτωση, | + | Στο παραπάνω απλό παράδειγμα είναι προφανές ότι είναι πιο απλό να ελέγξει κανείς το μέγεθος της παραμέτρου //size// πριν καλέσει τον κατασκευαστή. Σε αυτή την περίπτωση, |
</ | </ | ||
+ | |||
===== Τύποι παραγόμενων εξαιρέσεων ===== | ===== Τύποι παραγόμενων εξαιρέσεων ===== | ||
Line 151: | Line 155: | ||
cout << "Enter option (1-5): "; | cout << "Enter option (1-5): "; | ||
cin >> option; | cin >> option; | ||
- | | + | |
MyException ex; | MyException ex; | ||
switch(option) { | switch(option) { | ||
Line 170: | Line 174: | ||
break; | break; | ||
default: | default: | ||
- | c = -10; throw c; // throw a character | + | c = -10; |
+ | | ||
break; | break; | ||
} | } | ||
Line 197: | Line 202: | ||
} | } | ||
</ | </ | ||
- | πιάνει όλους τους τύπους // | + | πιάνει όλους τους τύπους // |
</ | </ | ||
<WRAP tip 80% center round> | <WRAP tip 80% center round> | ||
- | Στον παραπάνω κώδικα μπορείτε να παρατηρήσετε τα διαφορετικά μηνύματα που παράγονται ανάλογα με τον τύπο της εξαίρεσης. Παρατηρήστε | + | Στον παραπάνω κώδικα μπορείτε να παρατηρήσετε τα διαφορετικά μηνύματα που παράγονται ανάλογα με τον τύπο της εξαίρεσης. Παρατηρήστε, ότι αν και παράγεται ένα αντικείμενο τύπου //char//, το οποίο χωράει σε ένα //int// δεν γίνεται κάποια αυτόματη μετατροπή τύπου, ώστε το //catch block// που πιάνει τύπους //int// να πιάσει και αντικείμενα τύπου |
</ | </ | ||
- | + | <WRAP tip 80% center round> | |
- | ===== Stack Unwinding ===== | + | Στον παραπάνω κώδικα παρατηρήστε ότι για τα αντικείμενα τύπου //std::string// και //MyException// διαχειριζόμαστε μία αναφορά στον παραγόμενο αντικείμενο |
- | + | </WRAP> | |
- | Κατά την δημιουργία ενός // | + | |
- | + | ||
- | <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// στο | + | |
- | + | ||
- | {{ : | + | |
- | + | ||
- | ===== Διαχείριση μίας εξαίρεσης και παραγωγή νέας εξαίρεσης κατά την | + | |
- | + | ||
- | Κάποιες φορές είναι επιθυμητό να διαχειριστούμε μία | + | |
- | + | ||
- | <code cpp PPMImageSample.cpp> | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | + | ||
- | using namespace std; | + | |
- | + | ||
- | class PPMImage { | + | |
- | int width, height, colordepth; | + | |
- | int **raster; | + | |
- | public: | + | |
- | PPMImage(char *filename) { | + | |
- | string str; | + | |
- | unsigned char red, green, blue; | + | |
- | ifstream in(filename); | + | |
- | if(!in.is_open()) { | + | |
- | std:: | + | |
- | throw fex; | + | |
- | } | + | |
- | try { | + | |
- | in >> str; | + | |
- | in >> str; | + | |
- | width = atoi(str.c_str()); | + | |
- | in >> str; | + | |
- | height = atoi(str.c_str()); | + | |
- | in >> str; | + | |
- | colordepth = atoi(str.c_str()); | + | |
- | raster = new int*[height]; | + | |
- | for(int row=0; row< | + | |
- | raster[row] = new int[width]; | + | |
- | for(int row=0; row< | + | |
- | for(int col=0; col< | + | |
- | cin >> str; | + | |
- | red = (unsigned char) atoi(str.c_str()); | + | |
- | cin >> str; | + | |
- | green = (unsigned char) atoi(str.c_str()); | + | |
- | cin >> str; | + | |
- | blue = (unsigned char) atoi(str.c_str()); | + | |
- | raster[row][col] = 0; | + | |
- | raster[row][col] = (red << 16) | (green << 8) | blue; | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | catch(std:: | + | |
- | cerr << " | + | |
- | in.close(); | + | |
- | throw ex; | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | ~PPMImage() { | + | |
- | for(int row=0; row< | + | |
- | delete raster[row]; | + | |
- | delete raster; | + | |
- | } | + | |
- | + | ||
- | int **getRaster() { return raster; } | + | |
- | + | ||
- | }; | + | |
- | + | ||
- | int main(int argc, char *argv[]) { | + | |
- | PPMImage *imgptr=nullptr; | + | |
- | try{ | + | |
- | imgptr = new PPMImage(argv[1]); | + | |
- | } | + | |
- | catch(ios_base:: | + | |
- | cerr << "File '" | + | |
- | } | + | |
- | catch(bad_alloc &ex) { | + | |
- | cerr << " | + | |
- | if (imgptr!=nullptr) { | + | |
- | cerr << " | + | |
- | if(imgptr-> | + | |
- | cerr << " | + | |
- | delete imgptr-> | + | |
- | } | + | |
- | else { | + | |
- | cerr << " | + | |
- | } | + | |
- | delete imgptr; | + | |
- | } | + | |
- | else { | + | |
- | cerr << " | + | |
- | } | + | |
- | } | + | |
- | delete imgptr; | + | |
- | return 0; | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Το ενδεικτικό | + | |
- | + | ||
- | <code cpp 3x2.ppm> | + | |
- | P3 | + | |
- | 3 -2 255 | + | |
- | 255 0 0 255 255 0 0 255 255 | + | |
- | 255 0 255 0 255 0 128 128 128 | + | |
- | </ | + | |
- | + | ||
- | Από τον παραπάνω κώδικα μπορούμε να συμπεράνουμε τα εξής: | + | |
- | - Εφόσον παράγεται | + | |
- | - Εάν εφαρμόσω τον τελεστή **delete** σε ένα δείκτη που έχει την τιμή **nullptr**, | + | |
- | + | ||
- | ==== Ένα 2ο παράδειγμα ==== | + | |
- | + | ||
- | Στο προηγούμενο παράδειγμα κάντε την εξής αλλαγή. Αντικαταστήστε το //catch block// στον κατασκευαστή με το παρακάτω: | + | |
- | + | ||
- | <code cpp> | + | |
- | catch(std:: | + | |
- | cerr << " | + | |
- | in.close(); | + | |
- | throw ex; | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Το //exception std:: | + | |
- | < | + | |
- | $> ./ | + | |
- | std:: | + | |
- | terminate called after throwing an instance of ' | + | |
- | what(): | + | |
- | Aborted (core dumped) | + | |
- | </ | + | |
- | + | ||
- | Ο λόγος που | + | |
- | + | ||
- | <code cpp> | + | |
- | catch(std:: | + | |
- | cerr << " | + | |
- | in.close(); | + | |
- | throw; | + | |
- | } | + | |
- | </ | + | |
- | ===== Δήλωση των | + | |
- | + | ||
- | Κατά τη δήλωση μίας συνάρτησης είναι δυνατόν να ορίσετε εάν αυτή μπορεί να παράγει κάποιου είδους // | + | |
- | - '' | + | |
- | - '' | + | |
- | - '' | + | |
- | + | ||
- | Τους παραπάνω ορισμούς είναι δυνατόν να τους συναντήσετε στις // | + | |
- | + | ||
- | /* | + | |
- | ===== Function try blocks ===== | + | |
- | */ | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
cpp/exception.txt · Last modified: 2023/05/15 14:01 by gthanos