2014-05-09 2 views
0

하나 또는 두 개의 매개 변수로 throw 할 수있는 자체 예외를 만들려고합니다. 그래서 내가 한 것은 예외의 생성자를 오버로드하는 것입니다. 그러나 두 번째 생성자는 호출되지 않는 것 같습니다. 여기 내 코드 :예외의 C++ 오버로드 생성자

코드 목록 -1.

코드 목록-2 :

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; 
}; 

나는이 방법을 호출 할 때, 예를 들어.

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 
} 

"디버깅 메시지"가 전혀 표시되지 않습니다. "첫 번째 생성자"에 대한 주석을 작성하면 오류가 발생하고 많은 경고가 표시됩니다.

오류 목록 -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&' 

편집 :

코드 목록-2 : 오류 코드는 다음과 같은 정의 할 수 있습니다.

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

누구든지 내가 잘못한 이유를 설명 할 수 있습니까? 미리 감사드립니다. 예를 들어,

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

을하지만 오히려 당신은 당신의 코드에서 다른 곳에서 최초의 생성자를 호출하기 때문에 : 마사는 지적

+0

는'MYERROR_CODE_2' 매크로입니까? 그 경우에 difinition을 게시 할 수 있습니까? – Rakib

+1

오류가 발생하는'throw' 행 (28)이 코드에서 보여준 것과 다릅니다. 질문을 수정하고 관련 정보를 추가 할 때주의하십시오. – Massa

+0

@Massa Jan Kukacka가 응답 한 것처럼 나쁘다. 내 코드의 잘못된 부분을 수정하고 있었다. –

답변

2

, 당신이 얻을 컴파일 오류가 있기 때문에 귀하의 예제 라인의 발생하지 않습니다

throw myException(MYERROR_CODE_2); 
1

이미 다른 사람들이 대답 한 것처럼 오류는 다른 곳에서 발생합니다. 언급 한 문제없이 프로그램을 컴파일하고 실행할 수 있습니다. 그러나 코드에는 다른 문제가 있습니다. what 메서드에 임시 을 만들고이 문자열로 유지되는 문자 배열 을 반환합니다. 이것은 메서드에서 복귀 한 후 string이 존재하지 않기 때문에 포인터가 잘못된 메모리를 가리키고 있기 때문에 정의되지 않은 동작입니다.

1

enum 유형이 ExceptionCode입니다. MYERROR_CODE_2ExceptionCode이 아니며 unsigned short이 아닙니다. ExceptionCode라는 변수도 있습니다. 이것은 잘못된 생각입니다. 그러지 마.

제쳐두고, std :: exception에서 파생 된 여러 유형이있는 것과 거의 같은 방법으로 오류 코드를 제거하고 각 오류 코드의 하위 클래스를 파생시키는 것이 좋습니다.

1

예를 들어 오류 코드에 대한 정의를 제공하면 모두 컴파일됩니다.

그러나 하루에 충돌을 일으키는 what() 함수에는 심각한 버그가 있습니다.

일시적으로 c_str()을 호출하고 이제 포인터가 해제 된 메모리로 포인터를 반환하고 있습니다. 이것은 매우 나쁘다.

예외에 문자열을 저장하고 생성자가 안전하도록 문자열을 작성해야합니다.

예 구비 :

#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; 
    } 


}