User Tools

Site Tools


cpp:exception_inheritance

Differences

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

Link to this comparison view

Next revision
Previous revision
cpp:exception_inheritance [2019/05/06 07:17] – created gthanoscpp:exception_inheritance [2023/05/15 14:08] (current) 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[64]; +
-    char *s = new char [64];+
     sprintf(s, "BaseException, a: %d\n", a);     sprintf(s, "BaseException, a: %d\n", a);
     return s;     return s;
Line 20: 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 28: 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 38: 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 46: 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 87: 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>
 #include <iostream> #include <iostream>
-#include "DerivedException.h"+#include "DerivedException.hpp"
 using namespace std; using namespace std;
  
Line 114: 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 133: 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.1557127067.txt.gz · Last modified: 2019/05/06 06:17 (external edit)