2011-09-12 2 views
2

저는 이전 C 스타일의 코드 일부를 리팩터링하여 C++ 코드와 더 잘 어울리게하려고합니다. 난 여전히 C++생성자는 오류를 어떻게보고해야합니까? 외부 플래그에 대한 포인터?

내가 작업하고있는 코드의 예에 조금 새로운 오전 나는 클래스를 개발의 생각

Errmsg foo{ 
    ErrMsg err = NoError; 
    /* 
    Some Processing 
    */ 
    err = foo_cleanup(err,/* some parameters*/); 
    /* 
    Some More Processing 
    */ 
    return err; 
} 

를 다음과 같습니다 그래서

class foo_class 
{ 
public: 
    foo_class(Errmsg errmsg_init&,/*Some other arguments */): 
     errmsg(&errmsg_init), 
     /*Initialize other parameters */{} 

    void foo_cleanup (/*Other parameters*/); 
    // same functionality, but since the source variable is available, 
    // it can be modified without having to return any variable 

    ~foo_class(){foo_cleanup(/*Parameters*/);} 

    /* 
    Member functions 
    */ 

private: 
    Errmsg* errmsg; 
    /*Some other parameters */ 
}; 

Errmsg foo{ 
    ErrMsg err = NoError; 
    foo_class foo_obj(err); 
    /* 
    Some Processing 
    */ 

    // The class would be 
    //cleaned up before returning 
    // and the err variable would be 
    //modified in the destructor 
    return err; 
} 

내가 가지고 있지만 이 접근법과 비슷한 것을 사용할 수 있었는지, 이것이 휴대용이 될지 모르겠습니다.

옳은 일입니까?

그렇지 않으면 참조로 변수 오류 메시지를 전달하는 대신 클래스를 초기화하기 위해 포인터를 사용합니까? 아니면 제가 할 수있는 일이 있습니까?

"반환 오류 메시지"접근 방식을 사용하는 외부 코드에 대한 많은 함수 호출이 있기 때문에 현재 단계에서 예외를 사용할 수 없습니다. 많은 기능/여전히 "반환 오류 메시지"접근 방식을 사용하여 외부 코드에서에 호출이 있기 때문에

답변

1

(그리고 즉시 사용할 수있는 상태로 객체를 가져옵니다), 예외 회피 코드는 nothrow_init이 따르는 기본 생성자를 호출 할 수 있습니다. (nothrow_init이 실패하면 손에 사용할 수없는 객체가 있고, 그들이 그것을 사용하지 않도록하는 것은 그들의 책임입니다.)

나중에 코드 기반의 다른 부분을 예외 사용 상태로 가져 오면 init의 코드는 스스로 던질 수있는 것을 호출합니다. 이 시점에서 nothrow_init이 던져 버릴 수있는 코드를 init 함수를 호출하지만 예외를 포착하여 오류 코드로 변환 할 수 있도록 코드를 이동할 수 있습니다. 내부 클래스라고 가정하면 결국 nothrow_init을 사용하지 않고 제거 할 수 있습니다.

0

나는 현재 단계에서 예외를 사용할 수 없습니다.

그런 다음 먼저 문제를 해결하십시오. 그런 다음 예외를 사용하십시오.

return new FooClass (local_error_code_variable); 

가 리턴 코드와 생성자 실패를 신호하려고하지 마십시오 : 그것은 이와 같은 잘못된 사용 사례를 허용하기 때문에

+0

-1 때문에 ... 많은 것들이 있습니다. 예외는 도구입니다. 모든 것을 무시하고 당신의 신념을 망치라고 말하는 것은 어떻게해야 하는가? 한 문장 응답은 거의 유용하지 않습니다. 제어 흐름으로서의 예외 ?? 등등 ... 제발 당신의 추론을 확장하고 나는 그것을 투표하고 내가 틀렸다는 말을거야. –

+0

내 대답과 링크 된 GOTW를 참조하십시오. 예외는 모든 상황에 적합하지 않지만, 그러한 상황에서는 *** 유효한 대안이 없습니다. 실패한 오브젝트 구성은 그 중 하나입니다. – spraff

+0

흐름 제어가 더 적합한 생성자에서 일을하지 않는 것은 어떻습니까? 때로는 이런 종류의 일을하기에 완벽하게 유효합니다. 이것은 분명히 여기 있지 않습니다. 정말로, 당신은 기회가 있다면 CHeyWeJustAddedANumberException을 던질 것입니다 : P –

1

코드는 위험합니다. 수 없습니다. 예외 사용.

예외를 리턴 코드로 랩 할 수 있으며 그 반대의 경우도 가능합니다.

class NewAPIClass { 
    NewAPIClass() { 
     error_code err = old_api_function(); 
     if (OLD_API_OK != err) 
      throw NewAPIException (err); 
    } 
} 

extern "C" error_code new_api_callback_function (argument arg) { 
    try { 
     NewAPIClass object; 
     object .do_work(); 
    } 
    catch (...) { 
     return OLD_API_ERROR; 
    } 
} 

int main() { 
    old_api_install_callback (new_api_callback_function); 
} 

예외가 중요합니다. GOTW articles이 많이 있으며 C++ 개발자로서의 목표를 이해해야합니다.

예외를 올바르게 사용하려면 새 코드를 작성하십시오. 이전 코드와 새 코드 사이의 경계를 칠 때마다 오류 유형을 변환하십시오. 그런데

는 예외 생성자가 실패에 대한 합리적인 방법입니다. C++을 매우 강력하게 만드는 열쇠 인 RAII의 일부입니다. 생성자가 불변성을 확립하고 예외가 사후 조건을 만족시키지 못한다는 신호를줍니다. 여기에 중요한 철학이 있습니다 : C++에서는 유효한 객체 만 존재해야합니다., RAII를 악용하여이 권리를 얻으면 계속 존재합니다. 객체는 프로그램의 유효성을 증명합니다.

struct foo_class { 
    foo_class() { } // default constructor cannot fail 
    Errmsg nothrow_init(/* other params */) throw() { 
     /* initialize other parameters */ 
    } 
    foo_class(/* other params */) { 
     if (nothrow_init(/* other params */) != ERRMSG_OK) { 
      throw something; 
     } 
    } 
}; 

이제 예외 사용하는 코드는 멀티를 호출 할 수 있습니다 : 당신은 가능하면해야 예외가 OK이다, 당신은 2 단계 건설 관용구를 사용할 수 있도록 호출 코드를 수정하는 것이 차치