#ifndef仅适用于“声明”部分?

时间:2016-08-01 12:50:34

标签: c++ include-guards

我有这个IGlobal.h文件:

#ifndef _IGLOBALS_
#define _IGLOBALS_

#define _USE_MATH_DEFINES

#define PLUG_NUM_CHANNELS 2
#define PLUG_NUM_PRESETS 1
#define PLUG_FPS 100
#define PLUG_PPQ 96
#define KNOB_NUM_FRAMES 128
#define PIANOROLL_MIN_NOTES 2
#define PIANOROLL_MAX_NOTES 8
#define PIANOROLL_MIN_VELOCITY 40
#define PIANOROLL_MAX_VELOCITY 127
#define PIANOROLL_PATTERN_LENGTH PLUG_PPQ * 4
#define LFO_NUM_SAMPLES 882
#define WAVEPLAYER_WIDTH 441
#define WAVEPLAYER_HEIGHT 136
#define WAVEPLAYER_PATH_LENGTH 256
#define ENVELOPE_MIN_VALUE 0.0001

#include <algorithm>
#include <random>
#include <chrono>
#include <math.h>
#include <cmath>
#include "IPlug_include_in_plug_hdr.h"

using namespace std;

// bitmaps
IBitmap gBitmapKnobGeneral;

#endif // !_IGLOBALS_ 

我经常在项目中包含.h / .cpp文件。 IBitmap是一个结构。

当我构建(编译)时,它说:

LNK1169 one or more multiply defined symbols found
LNK2005 "struct IBitmap gBitmapKnobGeneral" ?gBitmapKnobGeneral@@3UIBitmap@@A) already defined in ICustomControls.obj

事实上,每次我加入IGlobal.h时都会有。 #ifndef不应该丢弃这个问题吗?或者编译器只为declarations而不是definitions自动执行此操作?

3 个答案:

答案 0 :(得分:2)

回答问题#ifndef适用于整个文件。

问题是当你写IBitmap gBitmapKnobGeneral时;您将在包含标头的每个源文件中创建一个实例。 我假设你要做的是创建一个单一的全局实例。 在这种情况下,你会想写。

  extern IBitmap gBitmapKnobGeneral;
在IGlobal.h文件中

然后在你的一个源文件中创建一个实例,例如IGlobal.cpp

 IBitmap gBitmapKnobGeneral;

答案 1 :(得分:0)

在C ++头文件中没有编译,它们被粘贴&#34;到源(cpp)文件。每个源文件都维护着自己独立的#defines集 - 如果你把它放在一个cpp文件中

#define A 1

这又是另一个

#ifndef A
#error A is not defined
#endif

您收到错误&#34; A未定义&#34;。在你的情况下,包含标题IGlobal.h的每个源文件都会通过你的标题一次(#ifdef后卫防止它多次解析)并定义IBitmap gBitmapKnobGeneral;你的程序最终会有多个变量定义。要了解如何解决问题,请参阅其他答案和评论。

答案 2 :(得分:-1)

#ifndef检查标识符是否先前已定义,如果没有,则会包含#ifndef与相应#endif/#else之间的代码。 如果您之前定义了此标识符,则预处理后代码将不存在,因此我将检查问题是否包含在IGlobal.h中包含的文件或符号中的某个位置 - 可能是其中一个“常量”(例如PLUG_NUM_CHANNELS)也在其他地方。

编辑: 看看#pragma once - 在我看来,这是一个更清晰的解决方案,它可以为标识符省去很多麻烦。