C++ 编码标准 #define 头文件
c++ coding standard #define header files
我正在阅读《编码标准:101 Rules, Guidelines, and Best Practices》一书C++书,它说使用#define
不好用。当我查看一些头文件时,它们有很多#define
。如果使用#define
不好,为什么有这么多?谢谢。
>#define
是一种不好的做法,因为:
它们没有任何范围:
#define
不尊重作用域,因此无法创建类作用域命名空间。虽然变量可以在类中限定范围。
编译错误期间奇怪的神奇数字:
如果您使用的是#define
则在预编译时将其替换为预处理器 因此,如果在编译过程中收到错误,则会令人困惑,因为错误消息不会引用宏名称,而是引用值,并且它会出现一个突然的值,并且会浪费大量时间在代码中跟踪它。
调试问题:
同样出于#2中提到的相同原因,虽然调试#define
实际上不会提供太多帮助。
因此,最好使用 const
变量而不是#define
。
它们在上述所有方面都优于#define
。只有#define
真正有用的领域才是需要在代码中或定义包含标头保护时实际替换文本的地方。
为什么
#define
在 C 标准头文件中广泛使用?
我想到的一个原因是,在 C(与 C++ 不同(中,const
声明不产生常量表达式。这意味着在 C 标准中引入可变长度数组之前,不能编写类似以下内容的内容:
const int max_val = 100;
int foos[max_val];
因为在 C 中max_val
不是编译时常数,并且在引入 VLA 的数组下标之前需要编译时常数。
所以人们不得不把它写成:
#define MAX_VAL 100
int foos[MAX_VAL];
这可能指的是定义常量的旧 C 方法:
#define MAX_SOMETHING 100
int x = MAX_SOMETHING;
这些常量不是类型化的,它们使用字符串替换就地扩展,并且使调试变得更加困难,因为一旦编译了源代码,就不清楚该定义的来源。
一种更C++方法是:
const int max_something = 100;
int x = max_something;
由于这是一个强类型值,因此需要对其进行所有必需的检查和适当的转换。
另一个好处是,出于组织目的,可以将const
值放入命名空间和类中。#define
的范围是全球性的,因此冲突是一个问题,这会导致名称过长以避免冲突。
在 const
和 template
之间,允许一种元编程形式 C 本身不做,需要#define
的场合大大减少。不过,它并没有完全消除,因为如果没有#import
指令,您仍然需要添加旧的#ifndef __HEADER_FILE_NAME__
防护装置,以确保不会包含两次。
这本书的宽泛陈述不是那么正确 - #define
在宏等中占有一席之地,但对于定义常量,现在使用它不是一个好主意
例如
#define FOO 257
最好在
const int FOO=257;
这允许类型检查,因为随着 #define 这变得有点奇怪
char c=FOO;
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 在C++中使用变量而不是"#define"来指定数组大小是不是一种糟糕的做法?(C错误:在文件范围内
- 使用 [#define & #ifdef] 跨文件激活代码块
- 使用 GCC 对 C 文件进行部分预处理(不删除 "define" 指令)
- C++:在包含的头文件 (Arduino) 中使用 #define 常量
- 该文件中的代码类型*.cpp #define mdTyVzgFy4_0UFy9GimmM
- 可以一个#define一个文字字符串,其中包含用于资源文件的非ANSI字符的字符串
- 预处理器指令:为什么使用#Define的标题文件标识符与标头文件名不同
- #define 包含头文件 C++
- C++ 编码标准 #define 头文件
- 我们是否应该在.h和.cpp文件中都包含一个宏(#define)
- 找出.h文件之间的#define语句冲突
- Visual Studio 2010:使用define宏指定输出可执行文件
- 如何检查哪个 #define 被编译成二进制文件
- 根据 #define 动态编译文件
- #define在预编译头文件中无法识别.mm文件
- 添加预处理器#define来更改包含哪些头文件以及调用哪些函数