将业务逻辑功能实现为宏是一个好主意吗?
我继承了一些遗留的c ++代码,我发现很多业务逻辑函数都被实现为长而神秘的宏。
宏是否优于函数? 使用宏的一般原理是什么?
什么样的逻辑最适合宏?
以下是代码
的简单示例#define INSERT_VALUES(IN,ID,EO) {\
double evaluationOutput = EO;\
int controls = 0;\
int input_controls = m_input_controls[IN];\
if(m_value_list[IN].ShouldProcess())\
{\
evaluationOutput = m_evaluationOutput[IN];\
controls = m_controls[IN];\
}\
VALUE_EXIST(evaluationOutput,controls,input_controls,IN,ID,Adj);\
m_evaluationOutput[IN] = controls > 0 ? evaluationOutput : 0.0;\
m_controls[IN] = controls;\
m_input_controls[IN] = input_controls;\
}
答案 0 :(得分:6)
否。它们绝对不是功能的一般替代品。
宏能够处理代码本身不具备的功能,特别是在编译之前创建和修改令牌(代码)。
作为交换,他们失去了所有类型的安全性,几乎所有可用于实际代码的语法糖。
当你必须做一些代码无法完成的事情,或者需要有条件地存在代码(超级调试诸如内存跟踪之类的东西)时,宏会派上用场。它们在提供更简洁或更易读的方式来处理特定事物方面也有一些价值(常见的例子是#define SUCCESS(x) (x >= 0)
。但是,对于任何需要类型安全,异常捕获或由常用代码组成的代码它们不必在编译时发生变异,它们几乎从不适合。大多数似乎可能是宏的代码可能在实际代码中更安全地表达,这对业务逻辑很重要。
您可以获得的最接近的经验法则是在编译期间是否需要发生某些事情或更改。如果是这样,考虑宏,否则只需编码。请记住,模板算作代码,可以做很多你可能想要使用宏的东西,但可能会更安全一些。
答案 1 :(得分:6)
在 Effective C++ 中,Scott Meyers在第2项中指出:
首选
consts
,enums
和inlines
至#defines
具体指的是编写宏而不是函数的做法,Meyers说:
#define
指令的另一个常见(错误)用法是使用它 实现看起来像函数但不会产生开销的宏 函数调用。像这样的宏有很多缺点,只是考虑它们 痛苦。
幸运的是,你不必忍受这种废话。你可以得到 宏的所有效率加上所有可预测的行为和 通过使用内联模板键入常规函数的安全性 功能
[实际功能]遵守范围和访问规则。例如,它使 完美的感觉,谈论一个私人的内联功能 类。一般来说,用宏来做就没办法了。
具体回答您的问题:
#include
和(可能)#ifdef
/ #ifndef
。 正如迈耶斯在结束时所说:
现在还不是退出预处理器的时候,但你应该这样做 肯定会让它长时间和频繁的假期。
答案 2 :(得分:2)
长,含糊不清的东西都不好。如果存在性能问题的宏,则可以使用内联函数实现相同的结果。如果它们用于简化表达,那么如果你有时间和金钱来进行这样的努力,它们可以被重构为不那么神秘并且更容易维护。