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 revisionBoth sides next revision
cpp:exception [2018/05/18 13:45] – [Κληρονομικότητα] 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 214: Line 217:
 <code cpp DerivedException.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