Extend std::exception

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • dinopc
    New Member
    • Nov 2006
    • 6

    Extend std::exception

    Hello, i am italian, I apologize for my English.

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

    Code:
    #include <iostream.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <sys/types.h>
    #include <errno.h>
    #include <dirent.h>
    #include <stdarg.h>
    #include <list>
    #include <string>
    #include <vector>
    #include <exception>
    
    using namespace std;
    
    class Exception : public std::exception
    {
    public:
      Exception(const std::exception& e);
      
    	Exception(const Exception& e);
    	
    	Exception(const std::string& s);
    	
    	Exception& operator= (const Exception& rhs);
    	void swap(Exception& x);
    	
    	virtual ~Exception() throw();
    
    public:
    
    	virtual const string getMessage() const;
    
    	/**
    	 * Returns getMessage()
    	 */
    	virtual const char* what() const throw();
    
    private:
    	string            m_msg;
    };
    
    Exception::Exception(const std::string& s)
    {
      m_msg = s;
    } 
    
    Exception::Exception(const std::exception& e)
      : std::exception(e)
    {
    } 
    
    Exception::~Exception() throw()
    {
    }
    
    Exception& Exception::operator=(const Exception& rhs)
    {
        Exception(rhs).swap(*this);
        return *this;
    }
    
    void Exception::swap(Exception& rhs)
    {
      std::swap(static_cast<std::exception&>(*this), static_cast<std::exception&>(rhs));
      std::swap(m_msg, rhs.m_msg);
    }
    
    const string Exception::getMessage() const
    {
      return m_msg;
    }
    
    const char* Exception::what() const throw()
    {
      return getMessage().c_str();
    }
    
    int main()
    {
      string s("22");
    
      try
      {
        s.erase(10,10);
      }
      catch (Exception &tExc)
      {
        cout << tExc.getMessage() << endl;
      }
    
      return 0;
    }
    When I run this piece of code the program goes into 'core', Can you help me understand what's the problem?

    Thank you
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    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.

    Comment

    • Oralloy
      Recognized Expert Contributor
      • Jun 2010
      • 988

      #3
      @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!

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        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.

        Comment

        • Oralloy
          Recognized Expert Contributor
          • Jun 2010
          • 988

          #5
          @weaknessforcat s,

          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

          Comment

          • dinopc
            New Member
            • Nov 2006
            • 6

            #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?

            Comment

            • Banfa
              Recognized Expert Expert
              • Feb 2006
              • 9067

              #7
              change your catch statement to

              Code:
                catch (std::exception &e)
                {
                  cout << e.what() << endl;
                }

              Comment

              • dinopc
                New Member
                • Nov 2006
                • 6

                #8
                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.

                Comment

                • Oralloy
                  Recognized Expert Contributor
                  • Jun 2010
                  • 988

                  #9
                  @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.
                  Code:
                  catch (Exception &ex)
                  {
                    // does not catch std::exception
                    cout << "Caught Exception: << flush;
                    cout << ex.what() << endl << flush;
                  }
                  Hopefully that helps.

                  Luck!

                  Comment

                  • Banfa
                    Recognized Expert Expert
                    • Feb 2006
                    • 9067

                    #10
                    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

                    Code:
                    class MyException : public std::exception
                    {
                    ... class definition ...
                    }
                    
                    int main()
                    {
                        try
                        {
                            throw MyException();
                        }
                        catch(std::exception &e)
                        {
                            cout << "caught my exception" << endl;
                        }
                    }
                    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_ran ge (which also inherits std::exception) , the compiler can not convert std::out_of_ran ge to Exception (from your code) because std::out_of_ran ge 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?

                    Comment

                    • dinopc
                      New Member
                      • Nov 2006
                      • 6

                      #11
                      Thank you.

                      Comment

                      Working...