2010-11-22 4 views
0

사람들이 C++ 예외가 더 좋은 이유에 대해 머리를 터는 것처럼 보이지 않습니다. 예를 들어, 응용 프로그램에서 사용할 공유 객체에서 함수 객체를로드하는 응용 프로그램이 있습니다. 계속되는 내용은 다음과 같습니다.내 오류 처리 방법을 변경하는 방법

bool LoadFunctions() 
{ 
    //Get Function factory. 
    FunctionFactory& oFactory = GetFunctionFactory(); 
    //Create functions from the factory and use. 
} 

FunctionFactory& GetFunctionFactory() 
{ 
    //Get shared object handle. 
    void* pHandle = dlopen("someso.so"); 

    //Get function ptr for Factory getter. 
    typedef FunctionFactory* (*tpfFacGet)(); 
    tpfFacGet pF = static_cast<tpfFacGet>(dlsym(pHandle, "GetFactory")); 

    //Call function and return object. 
    return *((*pF)()); 
} 

이제는 많은 물건이 잘못 될 수 있습니다. 내가 항상 그렇게했던 것처럼 참조 대신 포인터를 반환 할 것이고, 그들이 NULL인지 확인하고 오류 메시지를 출력하고 그렇지 않은 경우 나옵니다. 이렇게하면 일이 잘못되어 어디에서 복구 할 수 있는지 알 수 있습니다 (즉, 팩토리를로드하고 하나의 함수 만로드하면 실패 할 수 있습니다). 필자가 이해할 수없는 것은 이러한 시나리오에서 예외를 사용하는 방법과 오류 메시지를 인쇄하고 qutting하는 대신 프로그램을 복구하는 방법입니다. 누군가가 C++ 방식으로이 작업을 수행하는 방법을 말해 줄 수 있습니까?

답변

2

우리는 리턴 코드조차 필요하지 않습니다. 문제점이 발생하면 예외 상태에 있어야합니다.

int main() 
{ 
    try 
    { 
     LoadFunctions(); 
     // if we're here, everything succeeded! 
    } 
    catch(std::exception _e) 
    { 
     // output exception message, quit gracefully 
    } 

    // IRRESPECTIVE OF SUCCESS/FAILURE WE END UP HERE 

    return 0; 
} // eo main 

편집 :

좋아, 당신이 LoadFunctions()이 실패 로딩 기능의 다른 방법을 가지고 있다고 할 수 있습니다. catch 핸들러에서 이것을 호출하고 싶은 유혹을 느낄 수도 있지만, 이런 방식으로 방금 복잡한 일을하는 방대한 양의 중첩 예외 핸들러가 생기게됩니다.

이제 우리는 디자인의 질문으로갑니다. LoadFunctions은 함수가로드되면 성공하고 그렇지 않으면 예외를 throw합니다. 함수를로드하는 대체 방법의 가상의 예제에서이 호출은 LoadFunctions 메서드 내에 있어야합니다. 이 대체 방법은 호출자가 볼 필요가 없습니다.

최상위 수준에서 우리는 결국 함수로 끝나거나 그렇지 않습니다. 좋은 예외 처리를 쓰고, 내 생각에 은 회색 영역을 제거하는 것에 관한 것입니다. 이 기능은 그것이하도록 지시 된대로했거나 그렇지 않습니다.

+0

"// 예외 메시지를 정상적으로 종료하십시오."- 이것은 내가 이해하지 못하는 것입니다. 그만두고 싶지 않으면? 그럼 내가 뭘해야하지? – nakiya

+0

종료하지 않으려면 catch 블록에 대신 수행 할 작업을 작성하십시오. – Simone

+0

쉽습니다. GetFunctionFactory 함수는 항상 일관된 결과를 반환하므로 매번 사용하지 않을 때마다 검사 할 필요가 없습니다. – daramarak

0

당신이 말한 것처럼 잘못 될 수있는 많은 것이 있습니다. 그런데 나쁜 캐스팅을 잡지 못할 것입니다. 심볼이 존재하지만 그 타입을 캐스팅하는 타입이 아니라면 나중에 심한 충격을 받게됩니다.

예외를 피하려면 어딘가에 오류를보고해야합니다. LoadFunctions 및 GetFunctionFactory()가 오류 처리 방법을 모르기 때문에 (로그에 기록 하시겠습니까? stderr로 인쇄 하시겠습니까? 메시지 상자를 만드시겠습니까?) 할 수있는 유일한 방법은 오류를 생성하는 것입니다.

C에서 일반적인 방법은 오류가 발생할 경우 오류를 넣을 수있는 매개 변수를 전달하고 각 함수가 성공하기 전에 "성공"을 확인하는 것입니다. 이것은 흐름을 다소 까다롭게 할 수 있습니다.

예외를 "throw"하는 C++의 개념은 각 함수를 통해 포인터 (또는 참조)를 계속 전달할 필요가 없다는 것을 의미합니다. 오류가 발생한 곳에서 오류를 생성하고 "throw"합니다. 마치 "소리 치는 것"과 같습니다. 이로 인해 소멸자의 정리 이외의 모든 코드가 오류를 필요한 방식으로 처리하는 포수를 찾을 때까지 중지됩니다.

예외는 일반적으로 읽기를 완료 한 방법 인 경우 "파일 끝"과 마주 치는 일반적인 오류가 아닌 오류 처리에만 사용해야합니다.

0

반환 값 (또는 다른 방법) 대신 예외를 사용하면 코드의 동작을 변경하지 않고 작성하고 구성하는 방법 만 변경할 수 있습니다. 즉, 기본적으로 먼저 특정 오류의 복구가 무엇인지 결정합니다. 오류가 더 많거나 적 으면 코드를 작성하여 수행하십시오. 대부분의 경험 많은 프로그래머 (모두 사실상)는 예외가 반환 값보다 훨씬 좋은 방법이라고 동의합니다. 몇 가지 기능의 짧은 예에서는 큰 차이점을 볼 수 없지만 수천 가지 기능과 유형의 실제 시스템에서는 명확하게 나타납니다. 나는 그것이 더 나은 방법에 대해 더 자세히 설명하지 않을 것이다. 어쨌든 기본적으로 예외를 사용하는 데 익숙해 져야한다고 제안합니다. 그러나 예외를 사용하는 데 약간의 미묘한 문제가 있습니다 (예 : RAII http://en.wikipedia.org/wiki/RAII) 궁극적으로 코드를 더 잘 만들지 만, 책에 대해 읽어야합니다 (여기서 설명 할 수는 없으며 제목). "Effective C++/Scott Meyer"가 확실히 "Exceptional C++/Herb Sutter"라는 책을 다루고 있다고 생각합니다. 이 책들은 어쨌든 읽지 않는다면 C++ 개발자에게 좋은 출발점이됩니다.