如何使用 Apache Thrift 在单个 catch 语句中捕获所有自定义异常?

How to catch all custom exceptions in a single catch statement with Apache Thrift?

我在 exception.thrift 中定义了许多不同的异常:

exception InvalidArgumentsError {
    1: string parameter
}

/**
* Server has an problem while executing a function. 
* Execution aborted.
*/
exception ServerInternalError {
    1: string parameter
}

/**
* Server answer is empty.
*/
exception NoDataError {
    1: string parameter
}

这就是我在 C++ 代码中捕获它们的方式:

catch (InvalidArgumentsError & ex) {
  std::cout << ex.parameter;
}
catch (ServerInternalError & ex) {
  std::cout << ex.parameter;
}
catch (NoDataError & ex) {
  std::cout << ex.parameter;
}
catch (apache::thrift::TException& ex) {
  std::cout << "TException:\n" << ex.what();
} catch (const std::exception& ex) {
  std::cout << ex.what();
   return;
}

我想写这样的东西并捕获我所有的异常:

catch (SomeBasicException& ex) {
  std::cout << ex.what();
} 
catch (const std::exception& ex) {
  std::cout << ex.what();
}

如果我只是捕获 TException 并调用 what(),我只会收到 'Default TException' 消息,因为派生类不会覆盖虚拟 what() 方法。

thrift 编译器生成的代码:

class InvalidArgumentsError : public ::apache::thrift::TException {
 public:

  static const char* ascii_fingerprint; //..
  static const uint8_t binary_fingerprint[16]; //..

  InvalidArgumentsError() : parameter() {
  }

  virtual ~InvalidArgumentsError() throw() {}

  std::string parameter;

  _InvalidArgumentsError__isset __isset;

  void __set_parameter(const std::string& val) {
    parameter = val;
  }

//...

};

如果您想停止重复输入,那么这可能是一个解决方案。

当你想捕获你的异常时,你可以这样写:

catch (...) {
    handle_exception(print_message);
}

print_message 是一个函数,可以对消息做任何你想做的事情(在这种情况下,打印它):

void print_message(char const* const msg)
{
    std::cout << msg;
}

handle_exception是这样写的:

template<typename F>
void handle_exception(F handler)
try {
    throw;
}
catch (InvalidArgumentsError const& ex) {
    handler(ex.parameter.c_str());
}
catch (ServerInternalError const& ex) {
    handler(ex.parameter.c_str());
}
catch (NoDataError const& ex) {
    handler(ex.parameter.c_str());
}
catch (apache::thrift::TException const& ex) {
    handler(ex.what());
}
catch (std::exception const& ex) {
    handler(ex.what());
}

要处理新异常,请将其添加到 handle_exception 函数的 catch 子句中。

尽管这并没有真正从字面上回答问题(@Simple 已经在这方面做得很好),但我想提出一种稍微不同的方法。

鉴于上面发布的代码:

exception InvalidArgumentsError {
    1: string parameter
}

exception ServerInternalError {
    1: string parameter
}

exception NoDataError {
    1: string parameter
}

如果我们查看该模式,我们可以 - 在不丢失任何信息且不会产生更大的不兼容性的情况下 - 将其更改为:

enum ErrorCode
  Success = 0, // always good to have some null value
  ServerInternalError = 1
  NoData = 2
  InvalidArguments = 3
  // add more errors here
}

exception MyServiceException {
    1: string parameter
    2: ErrorCode  code
}

我完全知道这可能不适合您的特定问题(例如,如果异常数据多于 1:parameter)。但在某些情况下,这种方法可能值得考虑。我自己用过好几次了。