2012-07-02 2 views
1

나는 비슷한 질문을 여기에두고 있지만 확신 할 수 없다.여러 곳에서 예외의 전체 계층 구조를 처리하는 좋은 방법

여러 함수가 있다고 가정하면 전체 계층 구조의 예외가 발생할 수 있습니다. N 예외 클래스 유형을 예로 들어 보겠습니다.

이제 예외 코드를 여러 번 쓰는 대신에 Ncatch -block으로 여러 코드를 작성하는 것이 좋습니다.

내가 달성하는 (매우 못생긴) 방법은 매크로를 사용하는 것입니다. 다른 아이디어?

모든 기능을 다른 입력/출력 매개 변수이며, 반환 유형


편집

예, 모든 예외가 같은 기본 클래스를 가지고 - 그것이 계층 구조입니다. 그러나 다른 클래스에는 다른 추가 정보가 있습니다.

예 :

try 
{ 
    object->execute(...); 
} 
catch(type1& ex) 
{ 
    // ... 
} 
//... 
catch(typeN& ex) 
{ 
    // ... 
} 

// some other code 
// and again: 

try 
{ 
    object->do_something_else(...); 
} 
catch(type1& ex) 
{ 
    // ... 
} 
//... 
catch(typeN& ex) 
{ 
    // ... 
} 

// and so on 
+0

예외가 동일한 기본 클래스를 갖는 경우 하나의 처리기 만 작성할 수 있습니다. 다른 기능을 가진 예외를 어디서 처리하려고하는지 명확하지 않습니다. –

+0

@KirillKobelev - 기본 클래스가 동일합니다. 예, 계층 구조입니다. 그러나 다른 클래스에는 다른 추가 정보가 있습니다. 자세한 내용은 내 질문을 편집하겠습니다. –

답변

1

이러한 호출을 스위치가있는 하나의 함수로 결합 할 수 없다면 traget 함수의 각 호출에는 자체 try 블록이 있어야합니다.

기본 클래스를 catch하고 typeid 연산을 사용하는 공통 함수를 호출하거나 내부에서 발생할 수있는 예외 유형을 구분할 수 있습니다. 예외가 거의 발생하지 않으므로 RTTI 사용으로 인한 오버 헤드가 허용 될 수 있습니다.

+0

흠, RTTI에 대한 아이디어가 마음에 들어요. 나는 그것에 대해 생각할 것이다. –

+0

슬라이스를 방지하려면 참조로 잡으십시오. –

+0

@ChristopherCreutzig - 물론 :) –

3

이 예외의 기본 클래스에 대한 참조를 취 handleExceptions(Exception&)라는 함수를 확인합니다.

해당 기능에서는 예외와 함께 무엇이든 할 수 있습니다 (예 : Exception의 하위 클래스에 특정한 가상 메서드를 호출하십시오. dynamic_cast 등 실제로 예외가 무엇인지 정의 할 수도 있습니다.

2

실제 기본 유형을 전환하는 handleException 메소드에 대한 기본 클래스로 캡처하고 예외를 지정하는 것은 이미 언급되었습니다.

당신은 펑터를 소요하고 적절한 try..catch 안에 중첩 실행하는 기능 exception_check, 쓸 수있다 :이 작품을 만들기 위해 물론

template<typename Func> 
Func exception_check(Func fun) 
{ 
    try 
    { 
     func(); 
    } 
    catch(type1& ex) 
    {...} 
    //... 
    catch(typeN& ex) 
    {...} 
    return func; //in case the functor stores a result. 
} 

을 여기 주위에 다른 길을 간다 대안 approch이며, 결과 코드가 숨어서 못생긴 것없이 람다 함수가있는 C++ 11이 필요할 것입니다. 그렇지 않으면 많은 펑터에 코드가 분산 될 것이기 때문입니다. 람다 함수를 사용하면 간단하게 다음과 같이 호출 할 수 있습니다.

exception_check([&](){ object->execute(...); }); 
exception_check([&](){ object->do_something_else(...); }); 

개인적으로이 함수를 읽은 다음 각 함수 호출을 시도/catch하는 것이 좋다고 생각합니다.

물론 C++ 11에서는 복사하는 대신 펑터에 완벽한 전달을 사용하는 것이 좋습니다.

+0

커다란 프로젝트이기 때문에 C++ 11을 사용할 수 없습니다. 이전의 특정 플랫폼 (원래 gcc가있는 RHEL4)을 ​​위해 항상 컴파일되었지만 좋게 들립니다. 아직 C++ 11에 익숙하지 않으므로이 문제에 대해 다른 논점을 전달할 수있는 방법이 있습니까? 나는 이런 식으로 생각했기 때문에, (질문에서 언급 한) 다른 논증을 어떻게 통과시킬 수 있습니까? –

+0

@KirilKirov :'[&] (...) {...}'로 정의 된 람다는 람다 내부에서 사용되는 모든 변수를 참조로 포착합니다. 그래서'[&]() {object-> execute (...); }'는 본문에 언급 된 각 변수에 대한 참조를 저장합니다. 즉, 각기 다른 호출마다 다른 람다를 사용하기 만하면됩니다. C++ 11이 없으면 인라인 펑터가없고 변수를 포착하는 것이 피타이기 때문에이 방법은 훨씬 추악 해집니다. boost.Lambda (플랫폼에 맞게 사용 가능한 경우)를 사용하여 읽을 수있는 항목을 만들 수도 있지만 좋지는 않습니다. – Grizzly

+0

정말 대단합니다. +1 (다른 대답을 받아 들였습니다. C++ 03 :() –

관련 문제