By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,652 Members | 1,842 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,652 IT Pros & Developers. It's quick & easy.

Extend std::exception

P: 6
Hello, i am italian, I apologize for my English.

I would like to extend the class std::exception:

Expand|Select|Wrap|Line Numbers
  1. #include <iostream.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <ctype.h>
  5. #include <sys/types.h>
  6. #include <errno.h>
  7. #include <dirent.h>
  8. #include <stdarg.h>
  9. #include <list>
  10. #include <string>
  11. #include <vector>
  12. #include <exception>
  13.  
  14. using namespace std;
  15.  
  16. class Exception : public std::exception
  17. {
  18. public:
  19.   Exception(const std::exception& e);
  20.  
  21.     Exception(const Exception& e);
  22.  
  23.     Exception(const std::string& s);
  24.  
  25.     Exception& operator= (const Exception& rhs);
  26.     void swap(Exception& x);
  27.  
  28.     virtual ~Exception() throw();
  29.  
  30. public:
  31.  
  32.     virtual const string getMessage() const;
  33.  
  34.     /**
  35.      * Returns getMessage()
  36.      */
  37.     virtual const char* what() const throw();
  38.  
  39. private:
  40.     string            m_msg;
  41. };
  42.  
  43. Exception::Exception(const std::string& s)
  44. {
  45.   m_msg = s;
  46.  
  47. Exception::Exception(const std::exception& e)
  48.   : std::exception(e)
  49. {
  50.  
  51. Exception::~Exception() throw()
  52. {
  53. }
  54.  
  55. Exception& Exception::operator=(const Exception& rhs)
  56. {
  57.     Exception(rhs).swap(*this);
  58.     return *this;
  59. }
  60.  
  61. void Exception::swap(Exception& rhs)
  62. {
  63.   std::swap(static_cast<std::exception&>(*this), static_cast<std::exception&>(rhs));
  64.   std::swap(m_msg, rhs.m_msg);
  65. }
  66.  
  67. const string Exception::getMessage() const
  68. {
  69.   return m_msg;
  70. }
  71.  
  72. const char* Exception::what() const throw()
  73. {
  74.   return getMessage().c_str();
  75. }
  76.  
  77. int main()
  78. {
  79.   string s("22");
  80.  
  81.   try
  82.   {
  83.     s.erase(10,10);
  84.   }
  85.   catch (Exception &tExc)
  86.   {
  87.     cout << tExc.getMessage() << endl;
  88.   }
  89.  
  90.   return 0;
  91. }
  92.  
  93.  
When I run this piece of code the program goes into 'core', Can you help me understand what's the problem?

Thank you
Sep 8 '10 #1
Share this Question
Share on Google+
10 Replies


Banfa
Expert Mod 5K+
P: 8,916
If std::string is throwing an exception you are not catching it. std::string will be throwing either std::exception or more likely an exception derived from std::exception from the stdexcept header.

You catch your own exception, this will not be a match for the exception thrown by std::string, it can not be, std::string is compiled without access to your Exception class and so can not through that class. So the exception handler will not be entered because you have to catch the thing thrown or a super-class of the thing thrown. The unhandled exception then causes you program to core dump.


You derive from std::exception so that you have an exception that you can throw from your own code but that people using your code can catch easily using std::exception as well as all any other exceptions.
Sep 8 '10 #2

Oralloy
Expert 100+
P: 983
@dinopc,

May I ask why you're implementing assignment in terms of std::swap, which recurses back to your assignment? This recursion may well cause an infinite stack extension, ultimately resulting in a core dump.

Which is to say, I really don't understand your modified assignment operator - what are you trying to achieve?

Of course, my analysis of your code may be wrong, in which case, ignore me.

Cheers!
Sep 8 '10 #3

weaknessforcats
Expert Mod 5K+
P: 9,197
Also, when you derive from std::exception, you catch an std::exception reference and not an object of your own derived class.

virtual functions are used to get the correct what() call.
Sep 8 '10 #4

Oralloy
Expert 100+
P: 983
@weaknessforcats,

I respect your observation and judgement. What do you think he's trying to do with the assignment operator and std::swap invocations? That's what's got me confused.

Thanks,
Oralloy
Sep 8 '10 #5

P: 6
I'm sorry but unfortunately I did not understand any of your comments.

The process goes Signal = [6].

Can you help me understand how can I fix this?
Sep 9 '10 #6

Banfa
Expert Mod 5K+
P: 8,916
change your catch statement to

Expand|Select|Wrap|Line Numbers
  1.   catch (std::exception &e)
  2.   {
  3.     cout << e.what() << endl;
  4.   }
Sep 9 '10 #7

P: 6
I wanted to avoid putting a 'catch (std:: exception & exc)' since I created a class that inherits from 'std:: exception', hoping to catch exceptions even standard, otherwise it makes no sense it inherit from 'std:: exception'.

Thank you.
Sep 9 '10 #8

Oralloy
Expert 100+
P: 983
@dinopc,

You do understand that your Exception is an instance of (is-a) std::exception, but that std::exception is not an instance of Exception?

It sounds like you're confusing the meaning of the "is-a" relationship.

Banfa's suggestion is that you catch all thrown std::exception instances at the top level - so you can actually look at the cause of your error. This trap will also catch all instances of Exception.

If you were to catch Exception, as in my example here, then your code will not catch std::exception; even though you've built a constructor which takes std::exception as the argument. This is because the exception stack looks at type, but does not implicitly coerce types in the way compiled code does. If it did, there'd be a massive processing cost, as the C++ run-time would have to inspect every exception at each step to determine if there was a conversion (object constructor, etc) which matched.
Expand|Select|Wrap|Line Numbers
  1. catch (Exception &ex)
  2. {
  3.   // does not catch std::exception
  4.   cout << "Caught Exception: << flush;
  5.   cout << ex.what() << endl << flush;
  6. }
Hopefully that helps.

Luck!
Sep 9 '10 #9

Banfa
Expert Mod 5K+
P: 8,916
No it makes sense to inherit from std::exception when you want to throw your own exceptions since it lets people catch them in a standard way (through std::exception).

When you catch an exception you have to catch what is thrown. That means that what is thrown has to be capable of being converted to what is being caught.

The compiler is capable of may different conversions but the one that applies here is its ability to convert a reference to a derived class to a reference to a base class.

That allows the following model to work

Expand|Select|Wrap|Line Numbers
  1. class MyException : public std::exception
  2. {
  3. ... class definition ...
  4. }
  5.  
  6. int main()
  7. {
  8.     try
  9.     {
  10.         throw MyException();
  11.     }
  12.     catch(std::exception &e)
  13.     {
  14.         cout << "caught my exception" << endl;
  15.     }
  16. }
  17.  
The compiler can catch the exception as std::exception because the compiler can convert MyException to std::exception because MyException inherits std::exception.

string::erase throws std::out_of_range (which also inherits std::exception), the compiler can not convert std::out_of_range to Exception (from your code) because std::out_of_range does not inherit Exception.


Your attempt to inherit from std::exception in order to catch exceptions thrown by the standard library (and others) is doomed to failure because of of type conversion works.

I suggest you just catch in the standard way I gave in post #7. Alternatively you could explain your motives for wanting to catch using this inherited class, what was it you hoped to gain?
Sep 9 '10 #10

P: 6
Thank you.
Sep 9 '10 #11

Post your reply

Sign in to post your reply or Sign up for a free account.