C ++中的自定义异常:在哪里定义它们?

时间:2020-06-25 09:47:36

标签: c++ exception namespaces file-structure

对于我当前的项目,我定期定义要捕获的自定义异常。

但是,我正在努力确定关于这些异常的定义的最佳代码结构。

最初,我只是定义了嵌套在我的类中的引发它们的异常,就像这样:

class Foo {
   struct CustomException : public std::runtime_error {
   }
   void TrySomething() {
     throw CustomException();
   }
};

但是,现在我正在使用模板类,如果不提供模板参数,则无法访问此异常。也就是说,我不能做:

template class <T>
class Foo {
   struct CustomException : public std::runtime_error {
   }
   void TrySomething() {
     throw CustomException();
   }
};

void SomeFunction() {
  try {
    Foo foo;
    foo.TrySomething();
  }
  catch (const Foo::CustomException& exc) {
  }
}

因为没有模板参数的Foo不是类。 我正在尝试找出最干净的解决方案是什么(可以对项目的其余部分进行重新设计以遵循选定的标准)。

想到的选项:

  • 为Foo创建接口并在其中放置异常类(这似乎有点过分,仅出于这个原因而创建了一个接口)
  • 将异常放入我专门为Foo创建的命名空间中
  • 在Foo周围放置“ free”例外(但我想是在项目名称空间中,我现在的项目现在没有该名称空间,但无论如何我都读过是一种很好的做法)
  • 将所有异常放入一个文件中,命名空间或结构中
  • 创建一个“ Exceptions”命名空间,并在我要添加一个命名空间时(在引发异常的类文件中)扩展该命名空间

2 个答案:

答案 0 :(得分:0)

如果您的异常确实与模板类有着千丝万缕的联系,但是独立于模板的特定实例,则使用类似模式

struct FooBase
{
   struct FooBaseException : public std::exception
   {
   };
};

template class <T> 
struct Foo : FooBase
{
};

是一种方式。空基类优化将适用,并且至少从概念上讲,您已经引入了模板实例化之间的某些关系。

展望未来,您可能会发现常见功能出现在基类中。

这种模式在1990年代很普遍,模板可能会导致代码膨胀,但在这种情况下,我也看到了这种用法。

答案 1 :(得分:0)

我真的不明白为什么您需要为异常做模板。 我相信该代码将满足您的所有需求。您可以为经常使用的异常创建枚举,也可以引发单个自定义异常。

    enum class ErrorCode {
      kErrorOne,
    };
    
    // Helper function to get an explanatory string for error
    inline std::string GetErrorString(ErrorCode error_code) {
      switch (error_code) {
        case ErrorCode::kErrorOne:
          return "Some error";
      }
      return {};
    }

    class CustomException : public std::runtime_error {
     public:
      explicit CustomException(ErrorCode error_code) : std::runtime_error{GetErrorString(error_code)} {}

  CustomException(const std::string& what)
      : std::runtime_error{what} {}    
    };

此外,您可以在这里查看a pretty similar question

相关问题