2016-08-01 1 views
1

J'ai telles que ce fichier IGlobal.h:#ifndef ne fonctionne que pour les parties "déclaration"?

#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_ 

que je souvent inclus .h/.cpp au sein du projet. IBitmap est une structure.

Quand je construis (compilation), il dit:

LNK1169 one or more multiply defined symbols found 
LNK2005 "struct IBitmap gBitmapKnobGeneral" [email protected]@[email protected]@A) already defined in ICustomControls.obj 

Et en fait, je l'ai pour chaque fois que je IGlobal.h inclus. Ne devriez-vous pas #ifndef éliminer ce problème? Ou le compilateur le fait-il automatiquement pour declarations et non definitions?

+3

Où est le '# endif'? Ou est-ce juste le début du fichier? Et pourriez-vous ajouter le message d'erreur entier, s'il vous plaît? Est-ce que 'IPlug_include_in_plug_hdr.h' inclut-guarded? BTW, je pense que '#define PIANOROLL_PATTERN_LENGTH PLUG_PPQ * 4' pourrait entraîner de mauvais problèmes de préprocesseur. Mieux vaut ajouter des parenthèses. – Downvoter

+2

En général, vous devez déclarer une variable dans un en-tête en tant qu'ext, puis la définir dans un fichier cpp. –

+0

@RetiredNinja: oui, habituellement! Mais si je ne le fais pas, le compilateur le fait automatiquement? – markzzz

Répondre

-1

#ifndef vérifie si l'identificateur a été défini précédemment, sinon, il comprend le code entre #ifndef et correspondant #endif/#else. Si vous avez défini cet identifiant plus tôt, le code ne sera pas présent après le prétraitement, donc je vérifierais si le problème ne se trouve pas dans les fichiers inclus ou les symboles définis dans IGlobal.h - peut-être une de ces "constantes" (par exemple PLUG_NUM_CHANNELS) est aussi ailleurs.

EDIT: regardez #pragma once - c'est à mon avis une solution plus propre qui évite beaucoup de problèmes avec les identifiants.

+0

Ou simplement utiliser '#undef _IGLOBALS_' avant de définir le garde d'inclusion. – Downvoter

+0

Peut-être, mais nous ne savons pas où le problème est - il pourrait être ailleurs (peut-être 'IPlug_include_in_plug_hdr.h'). Cela étant dit, je voudrais extraire globals à un fichier séparé et espace de noms - ce serait une solution plus propre à mon avis. – pierscin

+0

Non. Il dit 'LNK2005 \t "struct IBitmap gBitmapKnobGeneral"(gBitmapKnobGeneral @@ 3UIBitmap @@ A?) Déjà défini dans ICustomControls.obj \t' – markzzz

2

Pour répondre à la question #ifndef fonctionne pour le fichier entier.

Le problème est que lorsque vous écrivez IBitmap gBitmapKnobGeneral; vous allez créer une instance dans chaque fichier source incluant l'en-tête. Je suppose que ce que vous essayez de faire est de créer une seule instance globale. Dans ce cas, vous voudrez écrire.

extern IBitmap gBitmapKnobGeneral; 

dans le fichier IGlobal.h puis créer une instance dans l'un des fichiers que vous source par exemple IGlobal.cpp avec

IBitmap gBitmapKnobGeneral; 
+0

Bien sûr. Mais puisqu'il y a ifndef, il ne devrait pas recompiler ce fichier. Au lieu de cela, puisqu'il y a "définition", c'est le cas. Compilateur intelligent? – markzzz

+0

Je suppose que la meilleure façon de le dire est que pour chaque fichier source (unité) que vous compilez, les définitions sont réinitialisées. Ainsi, lorsque vous compilez le second fichier source, il crée également une variable globale appelée gBitmapKnobGeneral même si vous avez un ifndef. Ensuite, lorsque l'éditeur de liens essaie de fusionner les fichiers obj créés à partir des deux fichiers source, cela crée le problème. – Kennet

0

Dans les fichiers d'en-tête de C ne sont pas compilés, ils sont « collés » dans les fichiers source (cpp). Chaque fichier source maintient son propre ensemble indépendant de #defines - si vous mettez cela dans un fichier cpp

#define A 1 

et cela dans un autre

#ifndef A 
#error A is not defined 
#endif 

vous obtenez l'erreur « A n'est pas défini ». Dans votre cas, chaque fichier source qui inclut l'en-tête IGlobal.h passe une fois par votre en-tête (la garde #ifdef l'empêche d'analyser plusieurs fois) et définit le IBitmap gBitmapKnobGeneral; Votre programme se retrouve avec plusieurs définitions de la variable. Pour voir comment résoudre le problème, consultez les autres réponses et commentaires.

+0

"Votre programme se termine avec plusieurs définitions de la variable." Pourquoi ceci si (comme vous l'avez dit) il inclut l'en-tête une fois? Ce n'est pas clair. – markzzz