User Tools

Site Tools


cpp:exception_inheritance

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revision Both sides next revision
cpp:exception_inheritance [2019/05/06 08:01]
gthanos
cpp:exception_inheritance [2022/05/23 04:09]
gthanos
Line 3: Line 3:
 Ας υποθέσουμε ότι έχουμε τη σχέση κληρονομικότητας μεταξύ των κλάσεων **BaseException** και **DerivedException**, όπως παρακάτω: Ας υποθέσουμε ότι έχουμε τη σχέση κληρονομικότητας μεταξύ των κλάσεων **BaseException** και **DerivedException**, όπως παρακάτω:
  
-<code cpp BaseException.h>+<code cpp BaseException.hpp>
 using namespace std; using namespace std;
  
-class BaseException: public std::exception {+class BaseException {
 protected: protected:
   int a;   int a;
 +  char s[64];
 public: public:
   BaseException(int a) { this->a = a; }   BaseException(int a) { this->a = a; }
-  const char* what() const throw() { +  virtual char* message() {
-    char *s = new char [64];+
     sprintf(s, "BaseException, a: %d\n", a);     sprintf(s, "BaseException, a: %d\n", a);
     return s;     return s;
Line 19: Line 19:
 </code> </code>
  
-<code cpp DerivedException.h+<code cpp DerivedException.hpp
-#include "BaseException.h"+#include "BaseException.hpp"
 using namespace std; using namespace std;
  
Line 27: Line 27:
 public: public:
   DerivedException(int a, int b): BaseException(a) { this->b = b; }   DerivedException(int a, int b): BaseException(a) { this->b = b; }
-  const char* what() const throw() { +  char* message() {
-    char *s = new char [64];+
     sprintf(s, "DerivedException, a: %d, b: %d\n", a, b);     sprintf(s, "DerivedException, a: %d, b: %d\n", a, b);
     return s;     return s;
Line 37: Line 36:
 <code cpp ExceptionUse.cpp> <code cpp ExceptionUse.cpp>
 #include <iostream> #include <iostream>
-#include "DerivedException.h"+#include "DerivedException.hpp"
 using namespace std; using namespace std;
  
Line 45: Line 44:
     cout << "Enter option (1-2): ";     cout << "Enter option (1-2): ";
     cin >> option;     cin >> option;
-    BaseException bex(-2); +    BaseException baseEx(-2); 
-    DerivedException dex(4,5);+    DerivedException derivedEx(4,5);
     switch(option) {     switch(option) {
       case 1:       case 1:
-        throw bex;+        throw baseEx;
         break;         break;
       case 2:       case 2:
-        throw dex;+        throw derivedEx;
         break;         break;
     }     }
   } catch(BaseException ex) {   } catch(BaseException ex) {
-    cout << ex.what();+    cout << ex.message();
   } catch(DerivedException ex) {   } catch(DerivedException ex) {
-    cout << ex.what();+    cout << ex.message();
   }   }
   return 0;   return 0;
Line 86: Line 85:
 </code> </code>
  
-Παρατηρήστε ότι ενώ στην 2η περίπτωση παράγεται ένα //DerivedException// το αντικείμενο που τελικά λαμβάνουμε είναι τύπου //BaseException//. Εδώ θα πρέπει να τονίσουμε ότι η συνάρτηση //what()// είναι //virtual// πράγμα που σημαίνει ότι θα πρέπει να καλείται η κατάλληλη έκδοση της συνάρτησης με βάση τον τύπο του αντικειμένου για το οποίο καλείται, ανεξάρτητα από τον τύπο της η οποία δείχνει στο αντικείμενο (δες [[cpp:polymorphism|δυναμικό πολυμορφισμό]]).+Παρατηρήστε ότι ενώ στην 2η περίπτωση παράγεται ένα //DerivedException// το αντικείμενο που τελικά λαμβάνουμε είναι τύπου //BaseException//. Εδώ θα πρέπει να τονίσουμε ότι η συνάρτηση //message()// είναι //virtual// πράγμα που διαισθητικά μας οδηγεί στο συμπέρασμα ότι θα κληθεί η κατάλληλη έκδοση της συνάρτησης με βάση τον τύπο του αντικειμένου για το οποίο καλείται, ανεξάρτητα από τον τύπο της (δες [[cpp:polymorphism|δυναμικό πολυμορφισμό]]).
  
 Η απάντηση στο παραπάνω ερώτημα είναι ότι αν και παράγεται ένα αντικείμενο τύπου //DerivedException// αυτό γίνεται //catch// από το πρώτο //catch block//. Μέσα στο //catch block// το αρχικό αντικείμενο αντιγράφεται σε ένα άλλο αντικείμενο τύπου //BaseException//, διότι έχουμε κλήση με τιμή στο //catch block//. Πρακτικά αυτό σημαίνει ότι από το αρχικό αντικείμενο κρατάμε οτιδήποτε ανήκει στην κλάση //BaseException// και απορρίπτουμε το υπόλοιπο. Η απάντηση στο παραπάνω ερώτημα είναι ότι αν και παράγεται ένα αντικείμενο τύπου //DerivedException// αυτό γίνεται //catch// από το πρώτο //catch block//. Μέσα στο //catch block// το αρχικό αντικείμενο αντιγράφεται σε ένα άλλο αντικείμενο τύπου //BaseException//, διότι έχουμε κλήση με τιμή στο //catch block//. Πρακτικά αυτό σημαίνει ότι από το αρχικό αντικείμενο κρατάμε οτιδήποτε ανήκει στην κλάση //BaseException// και απορρίπτουμε το υπόλοιπο.
  
-Ο τρόπος για να δουλέψει σωστά ο παραπάνω κώδικας είναι μέσα στο //catch block// να μην περάσουμε το αντικείμενο γιατί δημιουργείται αντίγραφο, αλλά να περάσουμε μία αναφορά σε αυτό, όπως παρακάτω:+Ο τρόπος για να δουλέψει σωστά ο παραπάνω κώδικας είναι μέσα στο //catch block// να μην περάσουμε το αντικείμενο γιατί δημιουργείται αντίγραφο του, αλλά να περάσουμε μία αναφορά σε αυτό, όπως παρακάτω:
  
 <code cpp ExceptionUse.cpp> <code cpp ExceptionUse.cpp>
Line 113: Line 112:
     }     }
   } catch(BaseException &ex) {   } catch(BaseException &ex) {
-    cout << ex.what();+    cout << ex.message();
   } catch(DerivedException &ex) {   } catch(DerivedException &ex) {
-    cout << ex.what();+    cout << ex.message();
   }   }
   return 0;   return 0;
Line 132: Line 131:
  
 <WRAP tip 80% center round> <WRAP tip 80% center round>
-Το πιάσιμο μιας εξαίρεσης με χρήση αναφοράς για αντικείμενα σύνθετου τύπου (όχι char, int, long, double κλπ), διότι //α)// αποφεύγουμε την αντιγραφή του αντικειμένου μέσα στο //catch block// (πιο γρήγορος κώδικας) και //β)// αποφεύγουμε την "αποκοπή" μέρους του αντικειμένου της εξαίρεσης λόγω του χειρισμού της από ένα //catch block// βασικότερου τύπου από τον τύπο του αντικειμένου της εξαίρεσης.+Συνιστάται, η διαχείριση μιας εξαίρεσης με χρήση αναφοράς για αντικείμενα σύνθετου τύπου (δηλαδή όχι τύπου char, int, long, double κλπ), διότι //α)// αποφεύγουμε την αντιγραφή του αντικειμένου μέσα στο //catch block// (πιο γρήγορη κλήση) και //β)// αποφεύγουμε την "αποκοπή" μέρους του αντικειμένου της εξαίρεσης λόγω του χειρισμού της από ένα //catch block// βασικότερου τύπου.
 </WRAP> </WRAP>
  
cpp/exception_inheritance.txt · Last modified: 2023/05/15 14:08 by gthanos