0

我知道宏的陷阱,并在我真正想要的是一个函数时避免它们。

不过,我发现它们的帮助在于存储诸如“神奇”数字、文件名、字体名称等内容。所以像:

ProjectHeader.h

#ifndef __PROJECT_HEADER__
#define __PROJECT_HEADER__

#define kXMLFileName "scoresAndSettings.xml"

#define AUDIO_DATA_TYPE_FORMAT SInt16
#define NUM_AUDIO_BUFFERS 3
#define AUDIO_SAMPLE_RATE 44100.
#define NUM_AUDIO_CHANNELS 2

#define kGameFont @"Helvetica-Bold"
#define kGameFontSizeNormal 18
#define kGameFontSizeSmall 16
#define kGameFontSizeTiny 11

这些让我 (a) 将 UI 细节存储在一个我可以更改它们的地方,并且知道更改将在整个代码中传播,(b) 给它们一个名称来描述它们在代码中的功能,以及 (c) 使用代码自动完成来知道我实际上输入了正确的术语。

我相当有信心这不是一种糟糕的工作方式,但我想知道是否有人认为它是,如果是这样,如何做得更好。

这些可能有点狡猾,但我仍然觉得它们很有帮助:

#define __COPY_PROTECTION__
#define __SHOW_FPS__ NO
#define __SKIP_LAUNCH_SCREEN__ 0
#define __START_IN_GAMEPLAY__ 1
#define __START_IN_PREFS__ 0
#define __START_IN_WIN_SCENE__ 0
#define __AUTO_WIN_TESTING__ 0

(然后,在代码中的各个方面:

AppDelegate.h
if (__START_IN_GAMEPLAY__) {
 [self show:MyGameplay];
 return;
}
[self show:MainScreen];

)。这使我可以直接通过仅操作文件#define中的宏 d 来测试我正在处理的项目的任何部分。ProjectHeader.h

这个好吗?坏的?下次有没有更好的方法?

4

1 回答 1

1

首先,在你的第一组宏中,没有任何东西不能更好地用const变量来完成,至少在 C++ 中是这样:

char const kXMLFileName[] = "socresAndSettings.xml";
typedef SInt16 audioDataTypeFormat;
int const numAudioBuffers = 3;
//  ...

使用const而不是宏的好处是名称将服从范围;对于数值,还有一个优点是您可以更轻松地指定类型(如果不是int)。在误用的情况下,错误消息通常也更容易理解。

对于您的第二个块,很难说(但是您选择的名称会导致未定义的行为)。我的印象是这些将用于条件编译。如果是这样,那么它们必须是宏。但总的来说,条件编译是要避免的,除非你的目标是混淆。

这并不是说你永远不应该使用宏。例如,没有其他方法可以自动插入__FILE____LINE__记录原语。在与 Python 或其他定义 C API 的语言交互时,我也广泛使用它们:在 C API 中,“重载”是通过手动名称修改完成的,而在宏中粘贴令牌是唯一简单的实现方法这。

于 2012-05-28T12:56:58.720 回答