Zdravko Donev Zdravko Donev - 2 months ago 12
C++ Question

C++ Throwing same error message from different places in code

I want to throw the same error from different places.
Here's an example:

int devide(int a,int b)
{
if(b==0) {
throw "b must be different from 0";
}

return 0;
}

int mod(int a,int b)
{
if(b==0) {
throw "b must be different than 0";
}

return 0;
}


And in the main function:

int main()
{
try {
devide(1,0);
} catch(char const* e) {
cout << e << endl;
}
try {
mod(1,0);
} catch(char const* e) {
cout << e << endl;
}

return 0;
}


Now the output of the program is:

b must be different from 0
b must be different than 0


As you can see, the error by its nature is the same, but the error message is different. So what's the best practice that I can follow in this case, so it could be scalable? Let's say that I have 100 different types of exceptions, but when I throw an exception for
devisor to be different from 0
I want to get the same messege everywhere where the exception is thrown.

EDIT:
I was thinking for two options:


  1. For every exception that I may throw I will define my own class that will inherit
    std::exception
    . Every exception I can put in
    Exceptions.cpp
    .

  2. I can define one one
    class MyException
    that will inherit
    std::exception
    and in the constructor I will request an error string. And I can somewhere(I still can't think of where to put them) define static string constants that will describe the message. For instance, if I have already define
    MyException
    I can use it like this:

    int devide(int a,int b)
    {
    if(b==0) {
    throw new MyException(MyException::DEVISION_BY_ZERO);
    }
    }



Where
MyException::DEVISION_BY_ZERO
will be a string constant.

I think that the second approach requires less coding but doesn't seem really pretty to me.

So is there a better aproach than the two above?

Answer

The best you can do is to create your own exception and throw that.

class Exception : public std::exception
{
    public:                
        template< typename... Args >
        Exception( const std::string& msg, Args... args );

        virtual ~Exception() throw ();

        //! Overrides std::exception
        virtual const char* what() const throw();

    private:
        //! Log the message_
        void log() const;

    protected:
        std::string message_;
};

template< typename... Args >
Exception::Exception( const std::string& msg, Args... args )
    : message_( StrFmt::format( msg, args ... ) )
{
    log();
}

class MyException : public Exception
{
    MyException() : Exception( std::string("b must be different from 0") )
}

If you further plan to exit the program on uncaught exceptions, it is possible to install a termination handler, where you rethrow the exception.

static void terminate()
{
    static bool tried_rethrow = false;
    try
    {
        if ( !tried_rethrow )
        {
            tried_rethrow = true;
            throw;
        }
    }
    catch ( const std::runtime_error& err )
    {
        std::cout << err.what();
    }
    catch ( const Exception& err )
    {
        std::cout << err.what();
    }
    catch ( ... )
    {
    }
} 

and in your main.cpp:

std::set_terminate( terminate );

That way it is possible to handle all uncaught exceptions at a single place.