C++ C++;将函数实现为宏的优点/缺点

C++ C++;将函数实现为宏的优点/缺点,c++,macros,C++,Macros,将业务逻辑函数实现为宏是一个好主意吗 我继承了一些传统的C++代码,我发现了很多业务逻辑函数被实现为长的隐藏宏。 宏比函数有优势吗? 使用宏的基本原理是什么 什么样的逻辑最适合宏 下面是一个简单的代码示例 #define INSERT_VALUES(IN,ID,EO) {\ double evaluationOutput = EO;\

将业务逻辑函数实现为宏是一个好主意吗

<>我继承了一些传统的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;\

}

不。它们绝对不是功能的一般替代品。

宏能够完成代码本身无法完成的事情,特别是在编译之前创建和修改标记(代码)

作为交换,它们失去了所有类型安全性,以及几乎所有可用于实际代码的语法

当您必须执行代码无法完成的操作,或者需要代码有条件地存在(超级调试功能,如内存跟踪)时,宏就派上了用场。它们在提供更简洁或更易读的方法来做特定的事情方面也有一定的价值(一个常见的例子是
#define SUCCESS(x)(x>=0)
。但是,对于任何需要类型安全性、异常捕获或由经常使用的代码组成的、不必在编译时发生变化的代码,它们几乎都是不合适的。大多数看起来可能是宏的代码可能可以更安全地在实际代码中表达,这对业务逻辑很重要


你可以得到的最接近的规则是编译过程中是否需要发生或改变。如果是这样,请考虑宏,否则只需编码它。记住,模板计数为代码,可以做很多事情,你可能会尝试使用宏,但可以更安全。

长的,神秘的任何东西都不好。如果宏对于性能问题,您可以使用内联函数获得相同的结果。如果将内联函数用于简化表达式,则如果您有时间和金钱进行此项工作,则可以将其重构为不那么神秘且更易于维护。

在中,Scott Meyers在第2项中指出:

首选
常量
枚举
内联线
而不是
#定义

Meyers特别提到编写宏而不是函数的做法,他说:

#define
指令的另一个常见(错误)用法是用于 实现看起来像函数但不会产生开销的宏 函数调用

像这样的宏有很多缺点,只考虑它们是非常困难的 痛苦

幸运的是,你不必忍受这种胡说八道。你可以 宏的所有效率加上所有可预测的行为和 通过使用内联函数的模板,键入常规函数的安全性 功能

[实函数]遵守范围和访问规则。例如,它使 谈论一个内联函数对一个 一般来说,用宏是无法做到这一点的

具体回答您的问题:

  • 一些程序员编写宏而不是函数,以避免函数调用的开销——这是一种可疑的做法,通常没有什么可测量的好处
  • <> LI>程序员以前使用预处理器生成样板代码(也许还可以)。在现代C++中,处理器的使用应限于<代码> >包含< <代码> >(也许)<代码> > IFDEF < /> > />代码> IFNDEF < /COD>条件编译。< /LI>
正如Meyers在结束时指出的那样:

现在还不是退出预处理器的时候,但是您应该 一定要经常给它放长假


很少需要宏-过度使用宏是一种“代码气味”。从您继承的代码中,您的判断是什么?宏是否使事情变得有用?宏可以成为隐藏一些混乱/样板/重复代码的有用快捷方式。例如,通过short(可能参数化)在类中生成一些常见声明宏,但是,就业务逻辑而言,通过合理使用C++的ARM(模板、函数重载等)可以做得更好。为了实现简洁、可读和安全的代码。因此,一般来说,答案是:否。你确定它是C++代码,不是C?是的,代码是,并且一直是C++。在我的例子中宏的用法是用于业务逻辑(如果A> B,然后做C或填充数组等),而不是条件编译。许多函数也被定义为“定义MyMy宏”。(A,B,C,D)GET##A(),然后它继续下去。
#define ONE 1
是类型安全的。它不提供任何类型安全。宏操作简单的文本搜索和替换(或多或少),完全超出语言的安全规则。例如,模板被编译和类型检查(错误消息可能同样神秘)。我在使用宏时遇到的大多数有趣的问题要么与类型相关,要么来自错误的间距/调用的巧妙的新符号。“你可以做一些不安全的事情”与“你不能做任何安全的事情”不同。如果你想反对宏,至少要提出准确的论据。夸张会损害你的可信度。宏既不提供也不强制执行任何类型安全。标准规则在处理宏后适用,但不适用于宏;这最终成为使用宏的常见问题。没有任何地方说明或暗示宏不能生成代码符合型式系统,但它们本身完全在系统之外,没有固有的安全检查。它们通常被视为不符合型式安全,无论该示例如何,都应被视为不符合型式安全。