2010-11-22 4 views
1

안녕하세요, "제어가 무효 기능의 끝"에 도달했을 때 어떻게해야합니까? 내 오버로드 된 연산자가 시도하고 시도 범위에 returns *this ; catch하고 있습니다. 나는 이클립스를 사용하고시도하고 catch 할 때 C++ 반환 값

은 G ++ 컴파일러, 우분투 리눅스입니다

NNmatrix & operator*=(const NNmatrix<T> &mtrxB) 
     { 
      // A=2*3 B=3*4 return C=2*4 
      const UINT aRows = this->size1(); 
      const UINT aCols = this->size2(); 
      const UINT bRows = mtrxB.size1(); 
      const UINT bCols = mtrxB.size2(); 
      try 
      { 
       // if cols of first(this) matrix == rows of second matrix 
       if (aCols != bRows) throw bad_alloc(); 
       const UINT cRows = aRows;// = rows of first matrix 
       const UINT cCols = bCols; // = cols of second matrix 
       NNmatrix mtrxC(cRows, cCols); 
       T val; 
       for (UINT i = 0; i < cRows; i++) 
       { 
        for (UINT j = 0; j < cCols; j++) 
        { 
         val = 0; 
         for (UINT k = 0; k < bRows; k++) 
         { 
          val += this->matrix.at(i).at(k) * mtrxB.getElement(k, j); 
         } 
         mtrxC.setElement(i, j, val); 
        } 
       } 
       *this = mtrxC; 
       mtrxC.clear(); 
       return *this; 
      } 
      catch (exception& e) 
      { 
       cout<<"Dimension don't match: ("<<aRows<<","<<aCols<<") ("<<bRows<<","<<bCols<<")"<<endl; 
      } 
     } 
+2

코드를 게시하십시오 (사용중인 컴파일러). – egrunin

+0

경고를 수정해야합니다. 자, 문제를 보여주는 예제가 있습니까? –

+0

코드를 게시하십시오. 문제의 막연한 아이디어 만 얻을 수 있습니다. –

답변

8

함수가 void 이외의 값을 반환하면 모든 코드 경로가 값을 반환하는지 확인해야합니다.

재실행없이이 함수의 내부적으로 예외를 처리하는 경우 블록 내부에서가 아니라 무조건 함수의 끝에 return *this;을 사용하면 안됩니까?

EDIT : 아래 @ Mark의 주석에 따라 간단히 return 문을 이동하면 요청한 작업의 컨텍스트에서 치명적인 오류가 숨겨지고 프로세스에서 라이브러리의 신뢰성이 떨어집니다. 예외를 전파하는 것이 더 좋습니다. 즉, 내부 승법 오류를 처리하는 방법 인 경우 (합리적인 접근 방법 인 것처럼 보임).

Object& operator=(Object const& rhs) 
{ 
    try 
    { 
    // something 
    return *this; 
    } 
    catch(std::exception& e) 
    { 
    std::cerr << e.what() << '\n'; 
    } 
} 

이제 문제는 예외가 슬로우 (그리고 잡힌) 될 때 반환 않는 값이다 :

+1

함수의 마지막에 리턴 값을 넣으면 행렬 곱셈을 전혀 수행 할 수없는 특정 입력이 있다는 사실이 숨겨집니다. 정상적으로 돌아 오면 실제로 성공하지 못했을 때 성공한 것처럼 보입니다. 'catch' 블록을 완전히 nix 화하고 버그 코드가 발견되고 고쳐질 수 있도록 예외가 전파되도록하는 것이 낫지 않습니까? –

+0

@ 마크 B - 맞습니다. 코드가 있기 전에 게시했습니다. 예외 처리에 대한 *주의 사항에 유의하십시오. –

+0

@ 마크와 스티브, 나는 그 시도를 논평했다. 하지만 던지기 후에 무엇을 넣어야합니까 ???? –

0

경고가 return 문이없는 기능 중 비 뛰어난 제어 경로가 존재한다는 사실을 의미한다 .

catch 범위가 비슷한 수익을 내고 있습니까? 돌아올 예정이 아니라면, 다시 살릴 수도 있습니다.

4

는 기본적으로 나는 운영자가 보이는 것을 얻을? 응답은 아무것도 반환하지 않으므로 컴파일러는 무엇을해야합니까?

당신은 캐치 경로에 무엇을 결정해야합니다

  • 중 뭔가 (아마도 같은 예외, 또는 원하는대로의 또 다른)를 던져
  • 또는 return *this 오류
  • 살 수 있다면

    그러나 할당 연산자의 경우

, 난 강력하게 맹목적 try/ catch 블록을 적용하는 것보다 미묘하게 다른 던진 예외를 가지고 NOT 것이 좋습니다 것입니다.

편집 : 문제에

훨씬 더 간단한 방법은 일치하지 않는 경우 (아무것도 수정하지 않고) 먼저 throw 당신의 예외를 확인하고 어떤이에 대한 걱정없이 코드에 대해 이동하는 것 예외가 발생했습니다.

이것은 예외적 인 토지에서 개발하는 일반적인 방법입니다. 먼저 던질 수있는 일을 수행 한 다음 여기 저기 튀어 나오는 예외에 대해 걱정할 필요가 없습니다.

덧글으로, 당신은 bad_alloc을 던지려고하지 않습니다!예외 유형 carry 의미bad_alloc은 시스템이 메모리 요청을 수행 할 수 없으며 일부 매트릭스 구현이 잘못되었다는 의미가 아니라는 것을 의미합니다.

+0

마지막 단락에 대해 더 자세히 설명해 주시겠습니까? 첫 번째 장소에 Exception을 넣으면 안된다는 뜻입니까? –

4

문제에 대한 해결책은 이것이다 :

NNmatrix & operator*=(const NNmatrix<T> &mtrxB) 
     { 
      // A=2*3 B=3*4 return C=2*4 
      const UINT aRows = this->size1(); 
      const UINT aCols = this->size2(); 
      const UINT bRows = mtrxB.size1(); 
      const UINT bCols = mtrxB.size2(); 
      try 
      { 
       // if cols of first(this) matrix == rows of second matrix 
       if (aCols != bRows) throw bad_alloc(); 
       const UINT cRows = aRows;// = rows of first matrix 
       const UINT cCols = bCols; // = cols of second matrix 
       NNmatrix mtrxC(cRows, cCols); 
       T val; 
       for (UINT i = 0; i < cRows; i++) 
       { 
        for (UINT j = 0; j < cCols; j++) 
        { 
         val = 0; 
         for (UINT k = 0; k < bRows; k++) 
         { 
          val += this->matrix.at(i).at(k) * mtrxB.getElement(k, j); 
         } 
         mtrxC.setElement(i, j, val); 
        } 
       } 
       *this = mtrxC; 
       mtrxC.clear(); 
      } 
      catch (exception& e) 
      { 
       cout<<"Dimension don't match: ("<<aRows<<","<<aCols<<") ("<<bRows<<","<<bCols<<")"<<endl; 
       // let the exception propagate 
       throw; 
      } 

      // always return *this 
      return *this; 
     } 
0

나는 당신의 큰 디자인을 알고 있지만하지 않는 모든에서 일반적 오버로드 된 연산자 말았어야으로 실행되지-시간 오류 (예 : "=", "*"등은 예외를 던져서는 안됩니다.) 사용자가 +, - 등으로 행동 할 것으로 기대하기 때문입니다. 숫자의 경우.

사용자가 어떻게 이것을 호출 할 것인지 생각해보십시오. 당신이 그 (것)들을 같은의 편의를 할 것 같습니다 : 당신이 정말로, 당신은, 빼기, 추가 것이다 그 크기가 실행시 설정 매트릭스를 지원해야하는 경우,

NNMatrix<int> matrixA; // Obviously with real assignments... 
NNMatrix<int> matrixB; 
matrixA *= matrixB; 

이제와 곱하기 연산이 실패 할 수 있습니다. 나는 개인적으로 실제 연산자 , +, -, = 등을 오버로드하지 않을 것입니다. 예외가있는 경우에만 오류 신호를 보낼 수 있기 때문입니다.

생각해보십시오. 당신은 당신의 매트릭스 사업자에 대한 모든 호출에 안전을 위해 이런 일을하도록 사용자에게 요구하고 있습니다 :

try { 
    matrixA *= matrixB; 
} 
catch(bad_alloc& ba) { 
    // Handle runtime error 
} 

을 이제 누군가가 try-에서 통화의 모두를 감싸려고하고있다 확율은 무엇인가 잡기? 당신이 false를 반환하고 크기가 일치하지 않는 경우, 동일한 얻을 곱셈을하지 않으면

bool NNMatrix<T>::MultiplyBy(const NNMatrix<T>& other); 

: 그들이하더라도, 그것은 같은 일반 멤버 함수를 사용하는 대안보다 청소기는 없다 이전처럼 행동.

if(!matrixA.MultiplyBy(matrixB)) { 
    // Handle runtime error 
} 

가 반환을 확인하는 것을 잊지 경우가 충돌의 원인이 결코 것이 더 나은 것입니다 : 이제 호출자는 같은 것을 필요로한다. 공용 API를 통해 사용자가 오류를 확인해야하며 작업이 완전히 성공했는지 실패했는지는 분명합니다. 그것은 여전히 ​​정숙하지는 못하지만 사용자가 'if()'논리를 갖고 있지 않다면 기대했던 것을 얻지 못할 것이지만 적어도 경고를 받았다. 필자가 아는 한, 컴파일 타임에 알 수없는 행과 열의 행렬을 지원해야하는 경우에 가장 좋은 방법입니다.