【问题标题】:Giant Try Catch Block in MainMain 中的 Giant Try Catch 块
【发布时间】:2017-07-03 04:35:38
【问题描述】:

我有一个可以在构造函数中抛出异常的类。我不知道拥有此类的代码,因此我无法更改此行为或向此类添加其他实例化或初始化方法。我需要在 main.js 中创建这个类的一个对象。这是否意味着我需要一个 main(),它主要由一个巨大的 try/catch 块组成,如下所示:

main()
{
  try
  {
    A a;
    ...
  }
  catch(std::exception& e)
  {
    std::cout << e.what() << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}

如果这个 main 有数千行长怎么办?这个 try/catch 块很大。我觉得应该有更好的方法来做到这一点,但我想不出一个。

【问题讨论】:

  • "如果这个 main 有几千行怎么办?"那将是您的问题,而不是 try/catch 块。
  • 用 try/catch 块包围这种可能失败(否则无法避免)的代码,而不是整个代码。您不需要依赖巨大的 try/catch 来处理项目中可能发生的任何错误,这也可能会捕获意外异常。
  • [main() 返回 int] main 中的 try-catch 块是(近乎普遍的)常见做法。 “...数千行长...”是恶毒的。
  • 即使一个人容易产生数千行长的函数,那又如何呢?如果你有一个巨大的 try/catch 块,为什么这很重要?这并不像它需要额外的打字。除非您手动键入所有缩进。
  • main() 中的代码行数与您程序中的代码量几乎没有对应关系。您可以将 main() 重命名为其他名称,例如 main_inner(),然后在 main() 的 try 块中调用 main_inner()。

标签: c++ exception-handling main


【解决方案1】:

有几种不同的方法可以处理这个问题。

main()的主体周围放一个function-try-block

int main() try
{
  A a;
  // use 'a' as needed ...
  return EXIT_SUCCESS;
}
catch (const std::exception& e)
{
  std::cout << e.what() << std::endl;
  return EXIT_FAILURE;
}

重构代码以将大部分 main() 移动到另一个函数,然后您可以在 try/except 块内调用该函数:

void run()
{
  A a;
  // use 'a' as needed ...
}

int main()
{
  try
  {
    run();
    return EXIT_SUCCESS;
  }
  catch (const std::exception& e)
  {
    std::cout << e.what() << std::endl;
    return EXIT_FAILURE;
  }
}

就个人而言,我只会在堆上而不是在堆栈上实例化类。这样,您可以将 try/catch 放在实例化周围:

#include <memory>

int main()
{
  std::unique_ptr<A> a; // or std::auto_ptr<A> prior to C++11...

  try
  {
    a.reset(new A);
    // or, in C++14 and later:
    // a = std::make_unique<A>();
  }
  catch(const std::exception& e)
  {
    std::cout << e.what() << std::endl;
    return EXIT_FAILURE;
  }

  // use 'a' as needed ...

  // the A object is freed automatically when 'a' goes out of scope...

  return EXIT_SUCCESS;
}

【讨论】:

    【解决方案2】:

    如果您没有明智的方法来处理异常,请不要打扰try 块。只是让异常逃脱并取消程序-替代方法是在“世界”不处于理智状态时继续-不是一个好主意。 当您没有理智的方法来处理错误时崩溃是合理的。捕获异常是你应该做的事情如果你有一个合理的方法来处理它们。默认情况下,只让它们传播。

    如果您可以合理地处理异常,请在对象的实例化周围添加try 块,然后在catch 块中进行合理的错误处理

    【讨论】:

      【解决方案3】:

      如果这个 main 有数千行长怎么办?
      ...我觉得应该有更好的方法来做到这一点,但我想不出一个。

      这显然是糟糕设计的标志,应该重构到类和函数调用中。

      最好是main() 中的类似内容:

      int main(int argc, char* argv[]) {
          try {
              Application app(argc,argv);
              app.run();
          }
          catch(std::exception& e) {
               std::cout << e.what() << std::endl;
               return EXIT_FAILURE;
          }
          return EXIT_SUCCESS;
      }      
      

      还是那个

      try {
          // Refactored 1000 lines of code
      }
      catch(std::exception& e) {
          std::cout << e.what() << std::endl;
          return EXIT_FAILURE;
      }
      

      必须附上调用代码。

      【讨论】:

      • 啊。我现在明白了。将所有内容封装到一个具有单个入口点的类中是我需要做的。在你有 Application::run() 的地方,我有大约 1000 行条件测试和函数调用。但是,将其全部放入“应用程序管理器”类中,该类了解需要做什么以及如何做是我所需要的。这允许单个函数调用并保持 main() 小而简洁。谢谢!
      【解决方案4】:

      这是否意味着我需要一个主要由一个巨大的 try / catch 块组成的 main()

      是的。

      如果这条主干线有数千行怎么办?

      不应该。让它不。将您的功能转变成函数

      不要忘记main() 的返回类型(即int)。

      【讨论】:

      • 有兴趣在这里发现反对者不同意的地方。
      猜你喜欢
      • 1970-01-01
      • 2016-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-21
      • 1970-01-01
      • 1970-01-01
      • 2012-01-14
      相关资源
      最近更新 更多