【问题标题】:need a robust error system for a win32 gui applicationwin32 gui 应用程序需要一个健壮的错误系统
【发布时间】:2013-02-27 21:12:36
【问题描述】:

我有一些代码如下:

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) 会自动关闭进度条。只有成功完成后,用户才能在此处单击“确定”。
  • MYCLASS_ERRORenum 中的一个值,其中包含各种 返回类型和状态。

我发现在SomeDialog点击确定后,仍然显示错误信息!我挖得更深了,发现MYCLASS_ERROR = IDOK = 1。

所以我的问题是,我应该如何定义所有这些返回状态,使其不会与任何其他实现的状态发生冲突?这意味着,我的函数应该返回 任何 其他函数(或尽可能少的其他函数)未返回的值。

我想修改我的设计,使所有函数只返回 TRUE 或 FALSE。但是,这并非在所有情况下都是可行的。我也搜索了很多答案,到目前为止还没有找到任何答案。

感谢收看!

【问题讨论】:

    标签: c++ windows mfc error-handling


    【解决方案1】:

    您可以使用枚举而不是宏定义的返回码,并带有命名空间以避免名称冲突。看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
    

    【讨论】:

    • 他的问题不是名称冲突,而是冲突。通过将error_policy_type::errno_on_error 定义为等于1,它仍然会与同样等于1 的IDOK 发生冲突。
    • 您可以声明一个没有值的枚举,并按原样使用。 Pros and Cons
    • 这里无关紧要。声明没有显式值的枚举仅意味着编译器将自动分配它们。在 99.99% 的实现中,它会按照您的预期进行,并从 0 开始分配并以 1 递增。
    • @georgesl,就像 Cody 说的那样,这会与各种 Win32 定义发生冲突。此外,我的错误目前也在 enum 中。
    【解决方案2】:

    有一些方法可以解决这个问题,但它们有点难看。

    最简洁的设计通常是避免与标准 Win32 习惯用法发生冲突的设计,在 Win32 的世界中,模式对话框返回 ID 值之一以指示用户在关闭它们时单击的按钮(就像消息箱)。严格来说是nResult参数传递给EndDialog函数用来关闭模态对话框。

    我建议不要试图用额外的意义重载这个返回值。尝试这样做只会给您带来麻烦(例如,您可能还没有注意到返回值 -1 意味着对话框创建失败)。


    相反,在您的对话框类中定义一个附加成员变量并使用它来报告您的附加信息。成功后,您将从对话框中返回 IDOK。失败时(任何种失败),返回类似IDCANCEL的内容。然后,OnButtonClick 中的代码将检查返回值是 IDOK 还是 IDCANCEL。如果是IDCANCEL,那么您需要查询您添加到对话框中的成员变量的值以获取更多信息。

    希望这是有道理的。如果不是,也许这个代码示例会(假设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.
            }
        }
    }
    

    【讨论】:

    • 嗯,这听起来最好。但是其他功能呢?例如,工作线程、辅助函数等。它们应该返回什么样的值?感谢您的回答!
    • @Anish:嗯,这有点难。您可能可以直接返回其中一个枚举错误代码,因为它们的返回值还没有标准的习惯用法。但是通过返回码进行错误处理很难做到正确,这只是原因之一。老实说,我想知道您是否不应该只使用异常。毕竟这是 C++,而不是 C。
    • 我会使用异常,但实际上我正在与许多用 C 编码的 DLL 进行交互。所以我想我会尝试让事情变得统一。但很可惜,它似乎不太好用。
    • @Anish 错误处理不必统一。显然 C DLL 必须返回错误代码,但这并不意味着使用它们的 C++ 函数也必须返回错误代码。我肯定会建议抛出异常。它们使您的生活在许多层面上变得如此轻松。 使用异常已经没有太多充分的理由了,尤其是在 UI 代码中(因为您使用的是 MFC,这似乎是您用 C++ 编写的)。即使异常是“缓慢的”(它们不再是),这在 UI 代码中也无关紧要。
    • 嗯,好吧。是时候复习我的异常知识了!非常感谢!如果可能的话,如果您有时间,请您指点我一些资源或任何可以让我开始制定良好的例外政策的东西吗?
    【解决方案3】:

    您可以简单地将自定义错误代码定义为不与 Windows 返回值“冲突”。当然,你不知道微软什么时候会添加新的返回值,所以这总是有点古怪。

    你可以试试这样的:

    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,而不是像那样重载返回代码。然后只需要有一个用户必须显式检索的辅助错误代码,这是您自己的“内部”错误代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-18
      • 1970-01-01
      • 1970-01-01
      • 2013-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多