【问题标题】:Using Define for throwing exceptions [closed]使用定义抛出异常[关闭]
【发布时间】:2014-05-30 09:13:37
【问题描述】:

目前,我正在重构一些由我们的前员工编写的旧项目。我遇到过用定义包装抛出异常的问题。

类似的东西:

#define THROWIT(msg) throw common::error(msg)

代码示例:

#define THROW_FD_ERROR( fd, op )\
throw common::error_fd( errno,\
    __ERR_FD_API_3\
    .arg( fd )\
    .arg( op )\
    .arg( strerror(errno) ),\
    __FILE__,\
    __LINE__ )

我可以看到它的一些好处,但它们对我来说并没有那么大。 无论如何,这是一种常见的技术吗? 您认为可以从中获得哪些优势? 您是否使用定义来抛出异常? 如果是的话,这样做的目的是什么?

UPD:从代码中添加定义

UPD2:感谢大家的回答。我决定去掉所有的宏。出于调试的目的,我将使用回溯信息扩展基本错误类,在我看来,这比仅对文件和行使用标准定义要好。

【问题讨论】:

  • 宏对此没有任何好处。但是,我通常定义一个布尔 fail 函数。它支持 perl 惯用的“做或死”表示法,该表示法简短且视觉上可识别而不会产生噪音。
  • 这确实是基于意见,但我看不出#DEFINE 有任何单一的好处。如果我真的需要一些复杂的逻辑(例如收集数据以附加到要抛出的异常),那么我会使用一个函数......
  • '不管怎样,它是一种常见的技术吗?'当然不是!
  • 在您的示例中,拥有这样的宏是没有意义的,除非它具有一些调试优势,例如使用 LINE。缩短字符数还会隐藏有用的信息,例如抛出的异常类型。
  • 我已经从代码中添加了定义。

标签: c++ exception throw


【解决方案1】:

通常,仅当您需要特定于预处理器的功能时才使用预处理器,例如__FILE____LINE__。这个宏没有做任何函数不能做的事情,因此它是非常不典型和糟糕的。

【讨论】:

  • 查看更新,在我看来它只是为了简化输入和一些调试信息。代码定义了每种可能的异常类型,它们在代码中被广泛使用。那么在您看来,将这种投入到“标准方式”的方式进行重构还是保持不变是否值得?
【解决方案2】:

所呈现的宏并没有太多好处。

但是,如果您想在异常消息中包含文件名、函数名和行号,宏可以有好处:

#define POSSIBLY_USEFUL_THROWIT(msg) throw common::error(__FILE__, __FUNCTION__, __LINE__, msg)

哦,THROWIT 是一个可怕的名字。


Alf 强调了一个好点:

您可以使用宏来收集信息,这是唯一的方法 去做吧。但是,将其与抛出异常联系起来是 责任合并。这意味着您需要单独的 用于日志记录、UI 消息等的宏。单个宏将 更可取。

我认为他的意思是有这样的东西:

// Construct new temporary object source_line_info
#define CURRENT_SRC_LINE_INFO() common::source_line_info(__FILE__, __FUNCTION__, __LINE__)

然后像这样使用它:

throw common::error(CURRENT_SRC_LINE_INFO(), msg);

只将真正需要的部分宏化。

就个人而言,我更希望有一个额外的宏,例如

#define THROW_COMMON_ERROR(...)  throw common::error(CURRENT_SRC_LINE_INFO(), ...

因为如果我将在多行上进行“宏调用”,我不妨让它尽可能短且集中,即使这意味着引入另一个宏。

【讨论】:

  • 您可以使用宏来收集信息,这是唯一的方法。但是,将其与抛出异常联系起来是职责的混合。这意味着您需要单独的此类宏用于日志记录、UI 消息等。单个宏会更好。
  • 这只是一个例子,代码包含每种异常类型的宏。 THROW_ERROR、THROW_FD_ERROR 等等。
【解决方案3】:

没有。不。坏的。它使代码更难理解,而且输入起来也不是那么短。

如果你真的必须,使用一个函数。但在这种情况下,我认为你真的不必这样做。

【讨论】:

    【解决方案4】:

    优点是要键入的字符更少,并且您可以在单个点(宏)更改 throw 声明(如抛出另一种类型)。但是,您也可以使用常用函数而不是宏。由于宏存在的问题(例如没有作用域以及可能污染包含宏定义头的其他文件),因此在函数可以完全相同的情况下使用宏被认为是不好的做法。宏最多是在没有其他工具时使用的工具语言功能可以做同样的事情,你迫切需要它。

    因此,我不会考虑这种好的做法。

    【讨论】:

      【解决方案5】:

      不,最好在 C++ 中使用内联函数。宏在没有编译器检查的情况下被替换。如果没有其他方法可以完成任务,则应使用预处理器宏。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-30
        • 1970-01-01
        • 1970-01-01
        • 2011-10-06
        • 2012-01-21
        相关资源
        最近更新 更多