2010-11-22 8 views
1

警告「制御が空でない関数の終了に達しました」という警告を出したとき、どうすればよいですか? 私のオーバーロードされた演算子はtryとcatchを持ち、returns *this ;はtryスコープにあります。私は、Eclipseを使用してい試してキャッチしたときのC++の戻り値

は、G ++コンパイラ、UbuntuのLinuxのある

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以外のものを返す場合は、すべてのコードパスが値を返すようにする必要があります。

再処理なしでこの関数の内部で例外を処理する場合は、tryブロック内からではなく、無条件に関数の最後に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'ブロックを完全に無効にし、例外を伝播させてバグのあるコードを見つけて修正できるようにする方が良いでしょうか? –

+0

@マークB - そうです:コードが存在する前に投稿しました。例外処理についての注意点に注意してください。 –

+0

@マークとスティーブ、私は試しにコメントした、キャッチします。私は投げた後に何を置くべきですか? –

0

警告がreturn文を持たない関数のうち非例外制御経路が存在することを意味します。

キャッチスコープの戻り値は同じですか?もしそれが返されるべきでなければ、あなたは転覆したいかもしれません。

4

は基本的に私はそれがあなたの作業のように見えることを得ますか? 応答は何も返さないので、コンパイラは何をすべきでしょうか?

あなたはキャッチパスに何をすべきかを決定する必要があります。

  • いずれかのエラーと一緒に暮らすことができれば何か(おそらく同じ例外、またはお好みの別)
  • またはreturn *thisを投げる
  • しかし、代入演算子の場合

、私は強く盲目的 try/ catchブロックを適用するよりも微妙に異なっているでスローされた例外を、持たないことをお勧めします。

EDIT:あなたの問題へ

Aはるかに簡単なアプローチは、それが一致しない場合(何も変更せずに)、最初のthrowあなたの例外を確認し、任意の心配することなく、あなたのコードについて行くことであろう例外が発生します。

これは、例外的な土地で開発する一般的な方法です。最初に投げ出すものを実行してください。次に、ここで例外が発生することを心配する必要はありません。

また、ご意見として、あなたはbad_allocを投げる気にしないでください!例外タイプの意味はとなり、bad_allocはシステムがメモリ要求を満たすことができず、一部のマトリックス実装が異常終了していないことを意味します。

+0

最後の段落についてもっと詳しく教えてください。これは私が最初に例外を置くべきではないという意味ですか? –

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-であなたの通話の一つ一つをラップしようとしていることオッズは何ですかキャッチ?彼らが行う場合であっても、それは代替よりもきれいではない、のような通常のメンバ関数を使用している:

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

あなたはfalseを返すと寸法が一致しない場合、乗算をしない場合は、同じことを得ますこれまで通りの行動。今、呼び出し側が唯一のようなものを必要とします:

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

これは、彼らがリターンをチェックするのを忘れた場合、これはクラッシュを引き起こすことがないという点で優れています。ユーザーがエラーをチェックする必要があり、操作が完全に成功するか失敗するかは、パブリックAPIから明らかです。確かにそれでもまだ綺麗ではなく、ユーザーは彼が 'if()'ロジックを持っていなければ何も期待しないが、少なくとも彼は警告されている。私が知る限り、これは、コンパイル時に未知数の行と列を持つ行列を実際にサポートしなければならない場合に、あなたができる最高のことです。

関連する問題