2011-07-05 5 views
10

C# 또는 Java로 작업 할 때 클래스 멤버로 다른 예외를 포함하는 예외 클래스를 작성했습니다. 예를 들어 :C++의 예외 내부 예외

public class MyException : Exception { 
    private MyException ex; 
    private String message; 

    public String what() { 
     return this.message; 
    } 

    public String stack() { 
     if(ex != null) { 
      StringBuilder s; 
      s.append(this.what()); 
      s.append(this.ex.stack()); 
      return s.toString(); 
     } 

     return this.what(); 
    } 
} 

나도 같은 주제에 있지만 C에 대한 예제를 찾고 있었다 ++ 나는 당신이이 질문의 제목을 볼 수있는이 (어쩌면 내가, 올바른 용어를 검색하지 않았다 찾을 수 없습니다 매우 공상적이지 않다).

어쨌든, C++에서 올바른 방법은 무엇입니까? 포인터 또는 참조로 내부 예외를 저장하는 것입니까? (포인터가 필요할 수도 있으므로 첫 번째 예외 일 때 null이 될 수 있습니다.) 예외를 발생시킬 때 포인터를 new으로 생성해야합니까?

편집 : 아마도 내가 쓴 것은 조금 혼란 스럽거나 잘 알려지지 않은 프로그래밍 연습이 아니었을 것입니다. 클래스 설계되지 않은 경우

try { 
    // Code that throws an exception of type MyException 
} catch(MyException ex) { 
    MyException another = new MyException(); 
    another.setEx(ex); 
    another.setMessage("A message that explains where the other exception was caught and on what conditions"); 

    throw another; 
} 
+3

C++에서는 여러 예외를 사용할 수 없습니다. 현재 예외가 잡히기 전에 새로운 예외가 던져지면 프로그램이 종료됩니다 (보다 정확하게'std :: terminate'가 호출됩니다). –

+0

@Gene : 이것은 새로운 예외 안에 기존의 예외가 채워지는 rethrow의 변형입니다 . 아마도 가비지 콜렉션 없이는 가능하지 않을 수 있습니다. –

+0

@Ben Voigt : 예외가 소멸자를 호출 할 때 정확하게 기억하는 것이 그리 어렵지 않은 경우 가비지 수집없이 가능할 것입니다. –

답변

0

나는 우리가 자바/C#을/C++의 클래스 인스턴스 속성 (예 : ex)를 필요가 있다고 생각하지 않습니다 그래서 나는 조각으로이 클래스를 사용하도록 구성하는 방법을 지정합니다 싱글 톤 패턴. 또한 here은 자습서 이기에 좋습니다.

+0

'MyException' 클래스 멤버는 다음과 같이 사용됩니다 : 1. 던져진 예외를 잡습니다. 2. 좀 더 구체적인 메시지로 ** 예외를 인스턴스화하고 'ex' 속성을 1에 잡힌 예외로 설정합니다. 3. 생성 된 새 예외를 던집니다. 당신이 나에게 보낸 튜토리얼입니다. – Renan

+0

역 참조 용으로 보관하고 싶습니다. 맞습니까? 그렇다면 왜 '예외'인스턴스가 아닌가? 게다가 원래 예외를 유지하기위한 역 참조 만 원하면 추적 메시지를 쌓아서 원래 예외를 버리는 것이 어떨까요? 아마 생성자에서? 나에게 더 많은 이유가있어. 내 2 센트 – shinkou

21

다형 적으로 사용하도록 설계되었지만 복제 할 수 없으므로 C++ 03의 표준 예외와 함께 올바른 방법은 없습니다. 따라서 std::exception const& e을 붙잡는다면 에 복사본을 저장할 수 있습니다. 그러나 이것은 유용한 정보를 모두 잃어 버리므로 조각이됩니다. 아니요catch 절을 끝내 자마자 수명이 끝나기 때문에 예외에 대한 포인터 또는 참조를 저장하지 않습니다 (원래 예외를 다시 발생시키지 않는다고 가정).

Throw 할 수있는 모든 유형을 모두 알고 테스트했지만 좋은 디자인이 아닌 경우 (즉, 다형성을 파괴 함)이 제한 사항을 극복 할 수 있습니다. 복제 될 수있는 기본 예외 클래스를 작성하고이를 포착하는 것이 더 합리적입니다. 그러나 누군가 다른 사람의 코드에서 나온 std::exception을 잡으면 여전히 문제가 발생합니다.

이 시점에서 나는 Boost.Exception을 언급 할 것을 강요 받았습니다. 사용자 고유의 예외 계층 구조를 쉽게 작성하고 boost::exception_ptr 사이의 다양한 유틸리티를 제공합니다. 당신은 할 수있다 :이 boost::diagnostic_info가 지원하는 너무 유용하고 (이것은 불법이다) 당신을위한 상자의 예외를 표시합니다

typedef boost::error_info<struct tag_nested_exception, boost::exception_ptr> 
    nested_exception; 

// ... 
catch(...) { 
    // better: use BOOST_THROW_EXCEPTION 
    throw your_exception_type() << nested_exception(boost::current_exception()); 
} 

. 이 nested_exceptiontypedef도 라이브러리에 포함되어야한다고 제안되었습니다. 그 동안에는 직접 작성하는 것이 쉽습니다.

마법을 예상하지 마십시오. 을 사용하는 경우에만 boost::current_exception은 활성 예외 (작은 글자 또는 그 복제본)를 '캡처합니다'. (기능적으로 이것은 복제 될 수있는 기본 예외 클래스를 사용하는 것과 도덕적으로 동일합니다. 그렇지 않은 경우 실패하지 않지만 일부 정보가 손실 될 수 있습니다.


마지막으로 Boost.Exception의 디자인이 C++ 0x에 채택되었음을 알았습니다.이 언어 지원이 있기 때문에 따라서 올바르게 다음은 boost::current_exception주의의 없음과, 활성 예외를 저장합니다

catch(...) { 
    // throws an unspecified type derived from your_exception_type 
    // and std::nested_exception 
    std::throw_with_nested(your_exception_type()); 
} 
+0

머리를 주셔서 감사합니다, C++ 0x 놀랄만 한 나를 유지 :) –

1

: 아주 쉽게과 같이 사용할 수있는 std::nested_exception 유형도 있습니다

// you can still use Boost.Exception: 
typedef boost::error_info<struct tag_nested_exception, std::exception_ptr> 
    nested_exception; 

// ... 
catch(...) { 
    // e has type std::exception_ptr 
    auto e = std::current_exception(); 
    // internally store the std::exception_ptr 
    throw your_exception_type(e); 

    // or with Boost 
    BOOST_THROW_EXCEPTION(your_exception_type() << nested_exception(e)); 
} 

unique_ptr<some_exception>을 던져서 inner_exception 또 다른 unique_ptr이라는 소유권을 얻습니다.

+0

그리고 당신은 polymorphically 행동하지 않기 때문에 동일한 기본 클래스에 대한 포인터가 던져 질 수 있는지 확인해야합니다. –

+0

@Luc : 확실히 단점이 있습니다. 그렇죠? –

+0

'std :: unique_ptr'이 C++ 0x라는 점을 감안할 때 더 나은 대안이 있다고 생각합니다. –