C++ 使用Define引发异常

C++ 使用Define引发异常,c++,exception,throw,C++,Exception,Throw,目前,我正在重构一些旧项目,这些项目是由我们的前员工编写的。我遇到过用define包装抛出异常的情况 诸如此类: #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(e

目前,我正在重构一些旧项目,这些项目是由我们的前员工编写的。我遇到过用define包装抛出异常的情况

诸如此类:

#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__ )
我可以看到它的一些好处,但以这样的方式做对我来说并不是很大。 不管怎样,这是一种常见的技术吗? 你认为它能带来什么好处? 您是否使用defines来引发异常? 如果是,目的是什么

UPD:从代码中添加define


UPD2:谢谢大家的回答。我决定去掉所有的宏。为了进行调试,我将使用backtrace信息扩展基本错误类,我认为这比只使用standart定义文件和行要好。

否。不要这样做。糟糕。它使代码更难理解,而且打字也不是那么短


如果您确实必须这样做,请使用函数。但我认为,在这种情况下,您真的不必这样做。

优点是可以键入的字符较少,并且可以在单个点(宏)更改抛出声明(就像抛出另一个类型一样)。但是,也可以使用普通函数而不是宏。使用函数可以完全相同的宏被认为是不好的做法,因为宏存在一些问题(例如没有范围和可能污染包含宏定义头的其他文件)。当没有其他语言功能可以做同样的事情时,宏最多是一个工具,您非常需要它


因此,我不认为这是一个好的实践。

< P>通常只使用预处理器,如果你需要一个预处理器特定的特性,比如<代码> >文件FieLe> 或Y.LynOx<。这个宏不做任何函数都不能的,因此它是不典型的和不好的。

< P>宏并没有太多的好处。> 但是,如果要在异常消息中包含文件名、函数名和行号,则宏可能会有好处:

#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);
然后像这样使用它:

// 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(), ...

因为如果我有一个“宏调用”在多行中,我最好尽可能短,尽可能集中,即使是引入另一个宏。

< P>不,最好在C++中使用内联函数。宏没有编译器的检查就被替换。预处理器宏应该在没有其他方式完成任务的情况下使用。r这一点。但是,我通常定义一个布尔
fail
函数。它支持perl惯用的“做或死”表示法,它很短,视觉上可以识别,没有噪音。它确实是基于观点的,但我看不到定义有任何好处。如果我真的需要一些复杂的逻辑(例如,收集要附加到要引发的异常的数据)然后我会使用一个函数…“不管怎样,这是一种常用技术吗?”当然不是!在您的示例中,使用这样的宏是毫无意义的,除非它有一些调试优势,比如使用行。缩短字符数也会隐藏一些有用的信息,比如引发异常的类型。我在代码中添加了定义。您可以使用cro来收集信息,这是唯一的方法。但是,将其与引发异常联系起来是职责的混合。这意味着您需要单独的宏来记录日志、UI消息等。最好使用单个宏。这只是一个示例,代码包含每种异常类型的宏。THROW_ERROR、THROW_FD_ERROR等等。我认为更新只是为了简化键入和一些调试信息。代码定义了每种可能的异常类型,它们在代码中被广泛使用。因此,在您看来,重构这种抛出到“标准方式”的方式还是就这样?