2010-04-06 6 views
1

발신자가 응답해야한다는 경고를 설정하는 방법을 찾고 있습니다. 어떤 의미에서 함수가 이미 실행을 끝내고 원하는 값을 반환 한 후에 발생하는 후기 예외 메카니즘을 사용하고 싶습니다.함수 호출자가 처리해야하는 경고

+4

실행을 계속할 수 있다면 왜 예외가 발생합니까? 예외는 예외적 인 상황을위한 것입니다. 어쨌든이 사용자는 프로그램의 기능 또는 사용자입니까? – GManNickG

+1

함수 사용자. 사용자가 경고 문제를 처리하도록 강요하고 싶지만 여전히 함수에서 결과를 얻고 싶습니다. 플래그를 사용하여 경고를 식별하는 경우 함수의 사용자가 경고를 무시하거나 플래그를 확인하는 것을 잊어 버리는 변경이 있습니다 ... – Hagai

+1

Right. 그래서 예외를 던지기 전에 함수가 끝날 때까지 기다리는 목적은 무엇입니까? 당신은 필연적으로 "내 모든 작업을 취소"하는 것을 지연하고 있습니다. "글쎄, 예외를 알릴 때를 말하는거야."라고 말할 수는 있지만 이제는 플래그를주는 것과 같은 배에 있습니다. 잊기 쉽습니다. 프로그래머가 무엇인가를 * assert *하려한다면, 당신은'assert'해야합니다. – GManNickG

답변

4

더 구체적인 결정을 내려야합니다. 사용자에게 기능을 경고하면서 (결과적으로) 결과를 제공하는 것은 매우 정통적입니다.

예를 들어 std::pair<SomeObject, std::string>을 반환 할 수 있습니다. 경고가있는 경우 경고가 문자열에 있습니다. 그러나 사람들이 그것을 무시하는 것은 매우 쉬울 것입니다.

예외는 해결책이 아닙니다. 의미있는 방식으로 실행을 계속할 수 있다면 예외는 아닙니다. 어딘가에 "대기열에있는"예외를 처리하게하는 시스템을 생각해 낼 수는 있지만 언제 던져야합니까? 그리고 무슨 목적으로? 어쨌든 그것은 나머지 작업을 끝낼 것입니다.

내가 원하는 것은 assert이라고 생각합니다. assert 조건이 true 인 경우; 그렇지 않은 경우 프로그래머에게 알림이 전송되고 이에 따라 상황을 처리 할 수 ​​있습니다. 기억하십시오. assert은 프로그래머를위한 것이며 예외는 프로그램을위한 것입니다.

아마도 우리가 좀 더 구체적인 예를 제시한다면, 우리는 최선의 행동 방침을 제안 할 수있을 것입니다.

0

"예외"를 던지고 "정상적인 값을 반환"을 계속합니다.

쓴대로 SomeObject의 일부 멤버 또는 생성자에 대한 참조로 전달 된 일부 변수에서 문제가 발생했음을 기억할 수 있습니다.

호출자가 오류를 처리하지 못하게하려면 호출자가 폴링하지 않으면 SomeObject의 소멸자 (또는 신호 멤버의 소멸자)를 선언하는 방식으로 "신호 멤버"를 구성 할 수 있습니다. . 신호 멤버의

가능한 예 : 값을 설정하고, 발신자가 "를 얻을"하지 않을 경우

template <typename Base> 
class Signal 
{ 
private: 
    Base _val; 
    bool _polled; 

public: 
    operator Base() const {_polled=true;return _val;} 
    // even when we do not set the value, we force the user to poll - it makes testing easier 
    Signal():_polled(false) {} 
    // but once we set it, we mark he has to poll 
    Signal(Base val):_val(val),_polled(false) {} 
    // if he does not, we assert 
    ~Signal(){assert(_polled);} 
}; 

은 소멸자가 주장하는 것입니다. 호출자가 그것을 얻을 수 있지만 어쨌든 무시한다면, 당신은 운이 없어진다. 그러나 예외는 예외이다. 호출자가 그것을 잡아 내고 무시하면, 그것에 대해 아무 것도 할 수 없다.

SomeObject Foo(int input, Signal<int> &errorCode) 
{ 
    SomeObject result;  
    // do something. 
    if (somethingBadHappened) 
    errorCode = 1234; //oh, we need to warn the caller. 

    return result; 
} 

void Main() 
{ 
    SomeObject object; 
    Signal<int> error; 
    object = Foo(1,error); 

    // error not served? => assert 
    // to prevent the assert firing, uncomment the following line 
    // int handle = error; 
} 

참고 : 대신 어설, 당신은 또한 신호 소멸자에서 예외를 던질 수 있었다 여기 당신이 그것을 사용하는 것이 방법이다. 하지만 소멸자로부터 던지기는 옳지 않다는 것을 알아 두십시오 - Signal 클래스를 정확히 사용하는 방법 (그리고 그 클래스를 위해 Base로 사용될 것임)에 대해주의 깊게 살펴야합니다.

+0

하지만 사용자가 해당 변수를 무시할 대상은 무엇입니까? – Hagai

+0

답변을 확장했습니다. 그것은 발사하고 단언 할 것이다. – Suma

+0

반환 형식을 Signal 로 변경하고 오류 코드를 가져 오는 메서드 외에도 반환 값을 가져 오는 메서드를 추가 할 수 있습니다. 그러나 나는 항상 오류 매개 변수를 사용하는 함수를 싫어했습니다. –

-1

예외가 발생하면 컴파일러는 현재 스택 프레임을 차례로보고 현재 발생하는 예외를 처리 할 수있는 catch 블록을 찾습니다.

컴파일러가 각 스택 프레임을 보면 해당 프레임의 모든 로컬 변수가 정리되므로 함수가 값을 반환하고 "함수가 이미 실행을 마친 후"예외가 throw 된 경우에도 컴파일러가 스택을 풀 때 반환 값은 정리됩니다. 함수가 끝나기를 기다리는 것은 무엇입니까? 그냥 예외를 던져서 다음을 던지십시오.

SomeObject foo(int input) 
{ 
    SomeObject result; 

    // Do stuff 

    // Something goes wrong in an unrecoverable fashion 
    throw BadThingHappenedException; 

    // More code for the good case 
    return result; 
} 
+0

스택이 이미 닫힌 후에 예외가 함수 밖으로 throw되어야합니다. 방법? 래퍼에 경고 플래그가 설정되었을 때 예외를 throw하는 함수의 반환 값에 대한 래퍼 객체 일 수 있습니다. 하지만 그 값은 여전히 ​​랩핑하는 데이터 객체에 존재합니다. – Hagai

+0

요점은 "데이터 객체에 여전히 존재하는"값이 필요한지 잘 모르겠다는 것입니다. 예외가 발생하면 컴파일러가됩니다. 어쨌든 사용자가 아무 것도 할 수 없기 전에 예외 처리기를 찾는 동안 해당 객체를 정리할 것입니다. –

+0

내가 수집해야 할 점은 저장해야하는 "유효한"반환 값이 여전히 있으므로 특별히 예외를 던지기를 원하지 않는다는 것입니다. 따라서 호출자가 예외를 포착하는 경우 객체를 전달한 다음 던져서 객체가 여전히 라이브 상태가되도록합니다. 그 종류의 "거의 성공한"국가. 내가 요청한 메모리는 할당했지만 원하는만큼만 절반을 할당 했으므로 크기를 확인하지 않으면 나중에 추락시키지 않고 현재 충돌 할 것입니다. –

관련 문제