User Tools

Site Tools


cpp:exception

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
Next revisionBoth sides next revision
cpp:exception [2018/05/18 14:54] – [Stack Unwinding] gthanoscpp:exception [2018/05/19 09:30] – [Stack Unwinding] gthanos
Line 196: Line 196:
 ===== Κληρονομικότητα ===== ===== Κληρονομικότητα =====
  
-Ας υποθέσουμε ότι έχουμε τη σχέση κληρονομικότητας μεταξύ των κλάσεων **IDException** και **CountedIDException**, όπως παρακάτω:+Ας υποθέσουμε ότι έχουμε τη σχέση κληρονομικότητας μεταξύ των κλάσεων **BaseException** και **DerivedException**, όπως παρακάτω:
  
 <code cpp BaseException.h> <code cpp BaseException.h>
Line 282: Line 282:
 </code> </code>
  
-Παρατηρήστε ότι ενώ στην 2η περίπτωση παράγεται ένα //DerivedException// το αντικείμενο που τελικά λαμβάνουμε είναι τύπου //BaseException//. Εδώ θα πρέπει να τονίσουμε ότι η συνάρτηση //what()// είναι //virtual// πράγμα που σημαίνει ότι θα πρέπει να καλείται η κατάλληλη συνάρτηση με βάση τον τύπο του αντικειμένου, ανεξάρτητα από τον τύπο της μεταβλητής.+Παρατηρήστε ότι ενώ στην 2η περίπτωση παράγεται ένα //DerivedException// το αντικείμενο που τελικά λαμβάνουμε είναι τύπου //BaseException//. Εδώ θα πρέπει να τονίσουμε ότι η συνάρτηση //what()// είναι //virtual// πράγμα που σημαίνει ότι θα πρέπει να καλείται η κατάλληλη έκδοση της συνάρτησης με βάση τον τύπο του αντικειμένου για το οποίο καλείται, ανεξάρτητα από τον τύπο της η οποία δείχνει στο αντικείμενο (δες [[cpp:polymorphism|δυναμικό πολυμορφισμό]]).
  
-Η απάντηση στο παραπάνω ερώτημα είναι ότι αν και παράγεται ένα αντικείμενο τύπου //DerivedException// αυτό γίνεται //catch// από το πρώτο //catch block//. Μέσα στο //catch block// το αρχικό αντικείμενο αντιγράφεται καθώς έχουμε κλήση με τιμή σε ένα άλλο αντικείμενο τύπου //BaseException//. Πρακτικά αυτό σημαίνει ότι από το αρχικό αντικείμενο κρατάμε οτιδήποτε ανήκει στην κλάση //BaseException// και απορρίπτουμε το υπόλοιπο.+Η απάντηση στο παραπάνω ερώτημα είναι ότι αν και παράγεται ένα αντικείμενο τύπου //DerivedException// αυτό γίνεται //catch// από το πρώτο //catch block//. Μέσα στο //catch block// το αρχικό αντικείμενο αντιγράφεται σε ένα άλλο αντικείμενο τύπου //BaseException//, διότι έχουμε κλήση με τιμή στο //catch block//. Πρακτικά αυτό σημαίνει ότι από το αρχικό αντικείμενο κρατάμε οτιδήποτε ανήκει στην κλάση //BaseException// και απορρίπτουμε το υπόλοιπο.
  
 Ο τρόπος για να δουλέψει σωστά ο παραπάνω κώδικας είναι μέσα στο //catch block// να μην περάσουμε το αντικείμενο γιατί δημιουργείται αντίγραφο, αλλά να περάσουμε μία αναφορά σε αυτό, όπως παρακάτω: Ο τρόπος για να δουλέψει σωστά ο παραπάνω κώδικας είναι μέσα στο //catch block// να μην περάσουμε το αντικείμενο γιατί δημιουργείται αντίγραφο, αλλά να περάσουμε μία αναφορά σε αυτό, όπως παρακάτω:
Line 327: Line 327:
 </code> </code>
  
 +<WRAP tip 80% center round>
 +Το πιάσιμο μιας εξαίρεσης με χρήση αναφοράς για αντικείμενα σύνθετους τύπου (όχ char, int, long, double κλπ), διότι //α)// αποφεύγουμε την αντιγραφή του αντικειμένου μέσα στο //catch block// (πιο γρήγορος κώδικας) και //β)// αποφεύγουμε την "αποκοπή" μέρους του αντικειμένου που γίνεται //throw// λόγω του "πιασίματος" της εξαίρεσης από ένα //catch block// βασικότερου τύπου από τον τύπο που γίνεται //throw//.
 +</WRAP>
 +
 +<WRAP tip 80% center round>
 +Είναι προφανές ότι η σειρά των //catch blocks// θα έπρεπε να είναι η αντίστροφη (πρώτα το //catch block// για την αναφορά τύπου //DerivedException// και στη συνέχεια το //catch block// για την αναφορά τύπου //BasedException//. Ο λόγος είναι ότι εάν παραμείνει η σειρά των //catch blocks// ως έχει το 2o catch block δεν εκτελείται ποτέ.
 +</WRAP>
 ===== Stack Unwinding ===== ===== Stack Unwinding =====
  
Line 381: Line 388:
 } }
 </code> </code>
 +
 +Το αποτέλεσμα που εκτυπώνεται στην οθόνη είναι το εξής:
 +<code>
 +Start main
 +Start F
 +Start FF
 +Start FFF
 +Start FFFF
 +FFFF throwing int literal exception
 +F caught int exception
 +End F
 +End main
 +</code>
 +
 +H εξέλιξη του //program stack// στο παρακάτω πρόγραμμα δίνεται στο παρακάτω διάγραμμα. Παρατηρήστε ότι το exception παράγεται στη συνάρτηση **FFFF()**, αλλά "πιάνεται" στην **F()** πράγμα που συνεπάγεται την αυτόματη συρρίκνωση του //stack// στο επίπεδο της συνάρτησης **F()**. Μετά το "πιάσιμο" του //exception//, τα περιεχόμενα του //stack// για τις συναρτήσεις **FFF()** και **FFFF()** έχουν χαθεί.
 +
 +{{ :cpp:stack_unwinding.png |}}
 +
 +===== Κλείσιμο ανοιχτών resources όταν συμβεί ένα exception =====
 +
 +1. Διάβασμα από αρχείο και δέσμευση διδιάστατου πίνακα.
 +
 +===== Exception Specifiers =====
 +
 +===== Function try blocks =====
 +
 +===== Η κλάση std::exception =====
 +
 +
  
  
cpp/exception.txt · Last modified: 2023/05/15 14:01 by gthanos