Reputation: 47945
I have such as this IGlobal.h file:
#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_
which I include often from .h/.cpp file within the project. IBitmap
is a struct.
When I Build (compile), it says:
LNK1169 one or more multiply defined symbols found
LNK2005 "struct IBitmap gBitmapKnobGeneral" ?gBitmapKnobGeneral@@3UIBitmap@@A) already defined in ICustomControls.obj
And in fact I have it for each time I include IGlobal.h. Shouldn't #ifndef discard this problem? Or compiler automatically does it only for declarations
and not definitions
?
Upvotes: 1
Views: 132
Reputation: 1109
In C++ header files are not compiled, they are "pasted" into source (cpp) files. Each source file maintains its own independent set of #defines - if you put this into one cpp file
#define A 1
and this into another one
#ifndef A
#error A is not defined
#endif
you get the error "A is not defined". In your case each source file which includes the header IGlobal.h gets through your header once (the #ifdef guard prevents it from parsing multiple times) and defines the IBitmap gBitmapKnobGeneral;
Your program ends up with multiple definitions of the variable. To see how to fix the problem see other answers and comments.
Upvotes: 0
Reputation: 353
To answer the question #ifndef works for the entire file.
The problem is that When you write IBitmap gBitmapKnobGeneral; you will create an instance in every source file that includes the header. I assume that what you are trying to do is create a single global instance. In that case you would want to write.
extern IBitmap gBitmapKnobGeneral;
in the IGlobal.h file and then create an instance in one of you source files for instance IGlobal.cpp with
IBitmap gBitmapKnobGeneral;
Upvotes: 2
Reputation: 710
#ifndef
checks whether identifier was defined previously, if not then it includes the code between #ifndef
and corresponding #endif/#else
.
If you defined this identifier earlier, then the code won't be there after preprocessing, so I would check if problem isn't somewhere in files included or symbols defined in IGlobal.h - maybe one of those "constants" (e.g. PLUG_NUM_CHANNELS) is also somewhere else.
EDIT:
look at #pragma once
- it is in my opinion cleaner solution which saves a lot of trouble with identifiers.
Upvotes: -1