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 13:44] – [Κληρονομικότητα] gthanoscpp:exception [2018/05/18 14:32] – [Κληρονομικότητα] gthanos
Line 199: Line 199:
  
 <code cpp BaseException.h> <code cpp BaseException.h>
 +using namespace std;
 +
 class BaseException: public std::exception { class BaseException: public std::exception {
 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]; +    //char s[64]; 
-    sprintf(s, "BaseException, a: %d", a);+    char *s = new char [64]; 
 +    sprintf(s, "BaseException, a: %d\n", a);
     return s;     return s;
   }   }
Line 212: Line 215:
 </code> </code>
  
-<code cpp CountedIDException.h>+<code cpp DerivedException.h>
 #include "BaseException.h" #include "BaseException.h"
 +using namespace std;
 +
 class DerivedException: public BaseException { class DerivedException: public BaseException {
   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 *= new char [64]; 
-    sprintf(s, "DerivedException, a: %d, b: %d", a, b);+    sprintf(s, "DerivedException, a: %d, b: %d\n", a, b);
     return s;     return s;
   }   }
Line 228: Line 233:
 <code cpp ExceptionUse.cpp> <code cpp ExceptionUse.cpp>
 #include <iostream> #include <iostream>
 +#include "DerivedException.h"
 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:
 } }
 </code> </code>
 +
 +O παραπάνω κώδικας παράγει το παρακάτω //warning// κατά τη μεταγλώττιση:
 +<code>
 +ExceptionUse.cpp:22:5: warning: exception of type ‘DerivedException’ will be caught
 +   } catch(DerivedException &ex) {
 +     ^
 +ExceptionUse.cpp:20:5: warning:    by earlier handler for ‘BaseException’
 +   } catch(BaseException &ex) {
 +     ^
 +</code>
 +
 +το οποίο εν συντομία λέει ότι ένα exception τύπου //DerivedException// θα "πιαστεί" από το 1ο //catch block// και το 2ο //catch block// δεν θα λειτουργήσει ποτέ. Το παραπάνω είναι λογικό διότι ένα αντικείμενο της κλάσης //DerivedException// είναι και //BaseException// με βάση τις αρχές της κληρονομικότητας.
 +
 +Εκτελέστε όμως τον παραπάνω κώδικα (παρά το warning) δίνοντας ορίσμα τους αριθμούς 1 και 2. Το αποτέλεσμα είναι το εξής:
 +<code>
 +gthanos@gthanos-DESKTOP:~/Downloads/C++$ ./ExceptionUse 
 +Enter option (1-2): 1
 +BaseException, a: -2
 +gthanos@gthanos-DESKTOP:~/Downloads/C++$ ./ExceptionUse 
 +Enter option (1-2): 2
 +BaseException, a: 4
 +</code>
 +
 +Παρατηρήστε ότι ενώ στην 2η περίπτωση παράγεται ένα //DerivedException// το αντικείμενο που τελικά λαμβάνουμε είναι τύπου //BaseException//. Εδώ θα πρέπει να τονίσουμε ότι η συνάρτηση //what()// είναι //virtual// πράγμα που σημαίνει ότι θα πρέπει να καλείται η κατάλληλη συνάρτηση με βάση τον τύπο του αντικειμένου, ανεξάρτητα από τον τύπο της μεταβλητής.
 +
 +Η απάντηση στο παραπάνω ερώτημα είναι ότι αν και παράγεται ένα αντικείμενο τύπου //DerivedException// αυτό γίνεται //catch// από το πρώτο //catch block//. Μέσα στο //catch block// το αρχικό αντικείμενο αντιγράφεται καθώς έχουμε κλήση με τιμή σε ένα άλλο αντικείμενο τύπου //BaseException//. Πρακτικά αυτό σημαίνει ότι από το αρχικό αντικείμενο κρατάμε οτιδήποτε ανήκει στην κλάση //BaseException// και απορρίπτουμε το υπόλοιπο.
 +
 +Ο τρόπος για να δουλέψει σωστά ο παραπάνω κώδικας είναι μέσα στο //catch block// να μην περάσουμε το αντικείμενο γιατί δημιουργείται αντίγραφο, αλλά να περάσουμε μία αναφορά σε αυτό, όπως παρακάτω:
 +
 +<code cpp ExceptionUse.cpp>
 +#include <iostream>
 +#include "DerivedException.h"
 +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;
 +}
 +</code>
 +
 +Πλέον το αποτέλεσμα της εκτέλεσης είναι το αναμενόμενο
 +<code>
 +gthanos@gthanos-DESKTOP:~/Downloads/C++$ ./ExceptionUse 
 +Enter option (1-2): 1
 +BaseException, a: -2
 +gthanos@gthanos-DESKTOP:~/Downloads/C++$ ./ExceptionUse 
 +Enter option (1-2): 2
 +DerivedException, a: 4, b: 5
 +</code>
 +
 +===== Stack Unwinding =====
 +
 +
 +
  
  
  
cpp/exception.txt · Last modified: 2023/05/15 14:01 by gthanos