Question

I try to make my own exception that I can throw with one or two parameters. So what I did was to overload the constructor of my exception. However the 2nd constructor seems not to be called. Here is my code:

code-listing-1.

class myException: public std::exception {
public:
    /*
     * first constructor
     */
    myException(unsigned short ExceptionCode):exception(){
        code = ExceptionCode;
        errorMessage = std::string("");
    }
    /*
     * second constructor
     */
    myException(unsigned short ExceptionCode, std::string errorMessage):exception(){
        std::cout << "debugging message";//present here for debugging purpose only
        code = ExceptionCode;
        this->errorMessage = errorMessage;
    }

    const char * what() const throw ()
    {   
        std::string tmp;
        switch(code){
            case MYERROR_CODE_1:
                tmp = std::string("MYERROR_CODE_1 : ");
                if(errorMessage.empty())
                    tmp += std::string("this is a default error message for code 1");
                tmp += errorMessage;
                break;
            case MYERROR_CODE_2:
                tmp = std::string("MYERROR_CODE_2 : ");
                if(errorMessage.empty())
                    tmp += std::string("this is a default error message for code 2");
                tmp += errorMessage;
        }


      return tmp.c_str();
    }
    ~myException() throw(){}

private:
    std::string errorMessage;
    unsigned short   code;
};

and for example when I call it this way:

code-listing-2.

void myFunction(myClass myObject){
    //some code
    if(conditionsMeet)
         throw myException(MYERROR_CODE_2,"this is a more specific custom message for code 2");
    //some other code
}

the "debugging message" doesn't appear at all. When I comment the "first constructor" I get an error and a lot of warnings.

error-listing-1.

main.cpp:28:41: error: no matching function for call to 'myException::myException(ExceptionCode)'
     throw myException(MYERROR_CODE_2);
                                         ^
main.cpp:28:41: note: candidates are:
In file included from Node.h:12:0,
                 from main.cpp:10:
myException.h:50:5: note: myException::myException(short unsigned int, std::string)
     myException(unsigned short ExceptionCode, std::string errorMessage):exception(){
     ^
myException.h:50:5: note:   candidate expects 2 arguments, 1 provided
myException.h:44:7: note: myException::myException(const myException&)
 class myException: public std::exception {
       ^
myException.h:44:7: note:   no known conversion for argument 1 from 'ExceptionCode' to 'const myException&'

edit: the error codes are define as such:

code-listing-2.

enum ExceptionCode{
    MYERROR_CODE_1                 = 1,
    MYERROR_CODE_2                 = 2,
};

can anyone explain to me what I did wrong and why? thanks in advance.

Was it helpful?

Solution

As Massa pointed out, the compilation error you get is not raised because of your example line:

throw myException(MYERROR_CODE_2,"this is a more specific custom message for code 2");

But rather because you call the first constructor somewhere else in your code, e.g.:

throw myException(MYERROR_CODE_2);

OTHER TIPS

Taking your example and providing definitions for the error codes, all compiles.

However, there is a serious bug in the what() function which will cause a crash one day.

You are calling c_str() on a temporary and then returning the pointer to memory that has now been freed. This is very very bad.

You need to store the string in the exception and build it during the constructor to be safe.

example provided:

#include <iostream>
#include <exception>

enum Errors {
    MYERROR_CODE_1,
    MYERROR_CODE_2
};


class myException: public std::exception {
public:
    /*
     * only one constructor necessary
     */
    myException(unsigned short ExceptionCode, std::string errorMessage = std::string())
    : exception()
    , message(buildErrorMessage(ExceptionCode, errorMessage))
    , code(ExceptionCode)
    {
        std::cout << "debugging message\n";//present here for debugging purpose only
    }

    static std::string buildErrorMessage(unsigned short code, const std::string& errorMessage) {
        std::string tmp;
        switch(code){
            case MYERROR_CODE_1:
                tmp = std::string("MYERROR_CODE_1 : ");
                if(errorMessage.empty())
                    tmp += std::string("this is a default error message for code 1");
                tmp += errorMessage;
                break;
            case MYERROR_CODE_2:
                tmp = std::string("MYERROR_CODE_2 : ");
                if(errorMessage.empty())
                    tmp += std::string("this is a default error message for code 2");
                tmp += errorMessage;
        }
        return tmp;
    }

    const char * what() const throw ()
    {   
        return message.c_str();
    }

private:
    std::string message;
    unsigned short   code;
};

using namespace std;

int main()
{
    int err = MYERROR_CODE_1;

    try {
        throw myException(err);
    }
    catch(exception& e) {
        cout << e.what() << endl;
    }

    try 
    {
        throw myException(err, "more info");
    }
    catch(exception& e) {
        cout << e.what() << endl;
    }


}

As already answered by others, the error is some where else. I could compile and run your program without the problem you mentioned. However, there is other problem in your code. You are creating a temporary string in what method, and returning the character array held by that string. This is Undefined behavior since after returning from the method, the string does not exist, and the pointer points to invalid memory.

You have an enum type ExceptionCode. MYERROR_CODE_2 is of type ExceptionCode, not unsigned short. You have variables also named ExceptionCode. This is a BAD IDEA. Don't do that.

As an aside, I suggest you get rid of the error codes and derive a subclass for each of the error codes, in much the same way that there are several types derived from std::exception.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top