为什么有std :: logic_error?

时间:2017-09-29 12:44:39

标签: c++

有人告诉我,你只会抛出异常处理外部问题",就像非内部问题一样,即只有运行时问题。但是我刚刚发现了std::logic_error异常,我开始问自己:为什么在你很可能不会抛出异常而不是使用assert或者只是内部逻辑时创建它,比如if / else语句?

2 个答案:

答案 0 :(得分:2)

请考虑此代码段,这是一百万行代码产品的一部分:

enum class Source_type
{
   type_a, type_b, type_c
};

class Resource
{
    Resource(const std::string& param1, int val1, int val2);
    Resource(Handle h1, int val1, int val2);
    Resource(Resource_builder rb, int v1, int v2);
};

Resouce create_resource_from_source(Source_type type, int v1, int v2)
{
   switch (type)
   {
       case Source_type::type_a:
       {
           std::string s = ...;
           return Resource{s, v1, v2};
       }
       case Source_type::type_b:
       {
           Handle h = ...;
           return Resource{h, v1, v2};
       }
       case Source_type::type_c;
       {
           Resource_builder b = ...;
           return Resouce{b, v1, v2};
       }
       default:
       {
           // should never reach here

           // however experience has painfully tough us that
           // leaving things that should never happen unchecked
           // will come back and bite us later

           // so what do we put here? <-----
           break;
        }
   }
};

一种解决方案是按照你的建议使用断言:

       default:
           // should never reach here

           assert(false);
           break;

然而,这会使您的应用程序崩溃。或者更糟糕的是,在发布版本中,这将导致未定义的行为,因为断言永远不会被检查,并且您到达了一个您不返回的分支。根据您的情况,这可能是不可接受的。例如,如果非常重要的是您的应用程序不会崩溃,即使出现此类错误也是如此。这里有例外:

  default:
           // should never reach here

           throw std::logic_exception{...}; // or custom exception
           break;

通过抛出异常,您现在可以选择优雅地恢复:

void some_ui_callback()
{
   Source_type type = ...;

   try
   {
       Resource r= create_resource_from_source(type, a, b);
   }
   catch(std::logic_exception& e)
   {
       showUserDialog("internal error. Please try again by selecting another option."
                      "Please submit a bug report...blah.. blah");
   }

   // or

   catch(std::logic_exception& e)
   {
      Resource r = create_fallback_resource(a, b);
   }
}

答案 1 :(得分:1)

在支持断言的语言中,您确实会使用断言机制而不是逻辑错误异常。

在c ++

在c ++ 20中,通过添加'contracts',可以使用'[[assert:expr]]'代替logic_error异常。

有关更多说明,请参阅Herb Sutter的文章https://herbsutter.com/2018/07/02/trip-report-summer-iso-c-standards-meeting-rapperswil/

相关问题