【问题标题】:How to catch all custom exceptions in a single catch statement with Apache Thrift?如何使用 Apache Thrift 在单个 catch 语句中捕获所有自定义异常?
【发布时间】:2016-02-22 20:49:48
【问题描述】:

我在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() 我只会收到“默认 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;
  }

//...

};

【问题讨论】:

  • 为什么要这样写?只是为了停止重复输入?
  • @Simple 是的,我有很多例外
  • in 0.9.3 what() 应该在生成的 TException 子类中被覆盖

标签: c++ rpc thrift c++03


【解决方案1】:

尽管这并没有真正从字面上回答这个问题(@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)。但在某些情况下,这种方法可能值得考虑。我自己用过好几次了。

【讨论】:

    【解决方案2】:

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

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

    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 子句中。

    【讨论】:

    • 很遗憾我没有使用c++11
    • 可以使用普通函数或函数对象,不一定是lambda。
    • 好的,我想我可以为此使用 boost::bind
    猜你喜欢
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 2018-05-23
    相关资源
    最近更新 更多