Joe*_*oel 10 c++ coding-style global-variables c-preprocessor
我已经开发了不到一年的C++,但在那段时间里,我听到很多人都在谈论有多糟糕#define.现在,我意识到它是由预处理器而不是编译器解释的,因此无法调试,但这真的那么糟糕吗?
这是一个例子(未经测试的代码,但你得到了一般的想法):
#define VERSION "1.2"
#include <string>
class Foo {
public:
string getVersion() {return "The current version is "+VERSION;}
};
Run Code Online (Sandbox Code Playgroud)
#define?Ben*_*ley 11
为什么这个代码不好?
因为VERSION可以被覆盖,编译器也不会告诉你.
有没有使用#define的替代方案?
const char * VERSION = "1.2";
Run Code Online (Sandbox Code Playgroud)
要么
const std::string VERSION = "1.2";
Run Code Online (Sandbox Code Playgroud)
Kon*_*lph 10
真正的问题是定义是由与其他语言(预处理器)不同的工具处理的.因此,编译器不知道它,并且在出现问题时无法帮助您 - 例如重用预处理器名称.
考虑max有时将其实现为宏的情况.因此,您无法max在代码中的任何位置使用标识符.任何地方.但编译器不会告诉你.相反,你的代码会出现严重错误,你不知道为什么.
现在,小心一点,这个问题可以最小化(如果没有完全消除).但是对于大多数用途而言,#define无论如何都有更好的替代方案,因此成本/收益计算变得偏差:轻微劣势,无论如何都没有任何好处.为什么在没有优势的情况下使用有缺陷的功能?
所以这是一个非常简单的图表:
"正确"地做它本身就是一门艺术,但有一些简单的指导方针:
使用唯一的名称.所有大写字母,始终以唯一的库标识符为前缀.max?出.VERSION?出.相反,使用MY_COOL_LIBRARY_MAX和MY_COOL_LIBRARY_VERSION.例如,Boost库,宏的大用户,总是使用以BOOST_<LIBRARY_NAME>_.开头的宏.
谨防评估.实际上,宏中的参数只是被替换的文本.因此,#define MY_LIB_MULTIPLY(x) x * x它被破坏了:它可以被用作MY_LIB_MULTIPLY(2 + 5),导致2 + 5 * 2 + 5.不是我们想要的.为了防止这种情况发生,总是充分利用这些论点的所有用法(除非你确切地知道你在做什么 - 扰流板:你可能不会这样做;甚至专家也常常惊慌失措).
这个宏的正确版本是:
#define MY_LIB_MULTIPLY(x) ((x) * (x))
Run Code Online (Sandbox Code Playgroud)但是仍然有很多方法可以让宏发生可怕的错误,重申一下,编译器在这里不会帮助你.
#define本质上并不是坏事,只是很容易被滥用。对于像版本字符串这样的东西,它工作得很好,虽然 aconst char*会更好,但许多程序员使用它的用途远不止于此。#define例如,使用typedef 是愚蠢的,而在大多数情况下,typedef 会更好。所以声明并没有什么错#define,有些事情没有声明就做不成。必须根据具体情况对它们进行评估。如果您能够找到一种不使用预处理器来解决问题的方法,那么您应该这样做。