5

次のようなコードがあります。

void MyClass::OnButtonClick()
{
    int retVal = SomeDialog.DoModal();
    if(retVal == MYCLASS_ERROR)
    {
        MessageBox("Error"...blah ...blah);
    }
    else if(retVal == IDOK)   // IDOK is returned on clicking the 'OK' button
    {
        MessageBox("All is well"...blah ...blah);
    }
}
  • SomeDialogプログレスバーを表示するだけです。エラーが発生すると、プログレス バーは を呼び出すことによって自動的に閉じられEndDialog(MYCLASS_ERROR)ます。正常に完了した場合にのみ、ユーザーは [OK] をクリックできます。
  • MYCLASS_ERRORは、enumあらゆる種類の戻り値の型とステータスを含む の値です。

で [OK] をクリックしてSomeDialogも、エラー メッセージがまだ表示されることがわかりました。もう少し深く掘り下げたところ、MYCLASS_ERROR= IDOK= 1 であることがわかりました。

だから私の質問は、他の実装のステータスと衝突しないように、これらすべての戻りステータスをどのように定義すればよいですか? つまり、私の関数は、他の関数によって返されない値を返す必要があります(または他の関数をできるだけ少なくする必要があります)。

すべての関数が TRUE または FALSE のみを返すように設計を変更することを考えました。しかし、これはすべての場合に実現可能というわけではありません。私も答えをかなり探しましたが、これまでのところ何も見つかりませんでした。

ご覧いただきありがとうございます。

4

3 に答える 3

3

これを回避する方法はいくつかありますが、それらはちょっと醜いです。

最もクリーンなデザインは通常、標準のWin32イディオムとの衝突を回避するデザインであり、Win32の世界では、モーダルダイアログはID値の1つを返し、ユーザーがボタンを閉じるときにクリックしたボタンを示します(メッセージボックスのように)。厳密に言えば、これはモーダルダイアログボックスを閉じるために使用される関数nResultに渡されたパラメーターです。EndDialog

この戻り値を追加の意味でオーバーロードしようとしないことをお勧めします。そうしようとすると、問題が発生します(たとえば、戻り値-1は、ダイアログボックスの作成に失敗したことを意味していることにまだ気付いていない可能性があります)


代わりに、ダイアログクラスで追加のメンバー変数を定義し、これを使用して追加情報を報告します。成功するとIDOK、ダイアログから戻ります。失敗(あらゆる種類の失敗)の場合は、のようなものを返しますIDCANCEL。中のコードは、戻り値がまたはであるかOnButtonClickどうかを確認します。の場合は、ダイアログに追加したメンバー変数の値を照会して、追加情報を取得する必要もあります。IDOKIDCANCELIDCANCEL

うまくいけば、それは理にかなっています。そうでない場合は、このコード例で次のようになります(これm_errStatusが、のサブクラスに追加したメンバー変数であると想定しますCDialog)。

void MyClass::OnButtonClick()
{
    if (SomeDialog.DoModal() == IDOK)
    {
        // Success!
        // The OK button was clicked, so IDOK was returned.
        MessageBox("All is well"...blah ...blah);
    }
    else
    {
        // Failure!
        // Some error occurred, so IDCANCEL (or any other value) was returned.
        // Determine what to do now, based on additional information that the
        // dialog set upon failure.
        switch (SomeDialog.m_errStatus)
        {
            case MYCLASS_ERROR_1:
                MessageBox("Error 1 occurred.");
                break;
            case MYCLASS_ERROR_2:
                MessageBox("Error 2 occurred.");
                break;
            // etc.
        }
    }
}
于 2013-03-12T11:50:38.973 に答える
1

Windows の戻り値と「衝突」しないように、カスタム エラー コードを定義するだけです。もちろん、Microsoft がいつ新しい戻り値を追加するかはわかりません。

次のようなことを試すことができます:

enum MYERR
{
    MYERR_FIRST_ERROR   = 0x0F000000, /* large and unlikely to be used */
    MYERR_SECOND_ERROR,
    MYERR_THIRD_ERROR,
    /* and so on */
};

しかし、Cody Gray が上で述べているように、リターン コードをそのようにオーバーロードするのではなく、DoModalから標準エラー コードを返す方がよいと思います。IDABORT次に、ユーザーが明示的に取得する必要がある二次エラー コードを用意します。これは、独自の「内部」エラー コードです。

于 2013-03-12T18:14:27.300 に答える
0

名前の競合を避けるために、マクロ定義の戻りコードの代わりに列挙型を名前空間とともに使用できます。Boost Error Handling Policyを見てください。

namespace boost { namespace math { namespace policies {

enum error_policy_type
{
   throw_on_error = 0, // throw an exception.
   errno_on_error = 1, // set ::errno & return 0, NaN, infinity or best guess.
   ignore_error = 2, // return 0, NaN, infinity or best guess.
   user_error = 3  // call a user-defined error handler.
};

}}} // namespaces
于 2013-03-12T11:34:23.703 に答える