2009-03-13 6 views
4

J'ai une classe de classe de matrice de matrice définie dans un en-tête appelé "Matrix.h".Comment éviter de redéclater accidentellement les constantes globales en C++?

Certaines matrices sont utilisées de façon répétée dans mon programme. Je pensais que je définirais ces derniers dans le fichier d'en-tête « Matrix.h », comme ceci:

const Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values); 

Quand je fais g ++ que je déplore la constante redéfini en question. Cela arrive parce que j'inclus Matrix.h dans deux fichiers source différents. Lorsque les fichiers d'objets pour ceux-ci sont compilés, les deux finissent avec une définition de la matrice ci-dessus, provoquant le message d'erreur.

Ma question est de savoir comment éviter cette situation? Je veux une constante accessible à plus d'un fichier, mais je ne sais pas où le mettre.

Répondre

6

Si vous ne voulez pas le diviser entre un en-tête et le fichier de mise en œuvre,

  1. Déclarez votre static constante (ou le déclarer dans l'espace de noms anonyme) pour faire la définition privée. Linker ne se plaindra pas, mais il en résultera plusieurs copies privées entre les unités de compilation.

    static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values); 
    
  2. Créez une fonction en ligne qui renvoie la constante. Les définitions de fonctions en ligne produisent des symboles "faibles" dans le fichier objet, de sorte que le lieur éliminera les doublons et en choisira un.

    inline const Matrix<GLfloat>& 
    GET_B_SPLINE_TO_BEZIER_MATRIX() { 
        const static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values); 
        return B_SPLINE_TO_BEZIER_MATRIX; 
    } 
    
+0

Merci beaucoup! Le mot-clé "statique" a fait disparaître tous mes problèmes :) – fluffels

+0

Il est cependant obsolète en faveur de namespace {}. – MSalters

+0

Et le second ne produira en fait pas de copies multiples: 7.1.2/4 "Une variable locale statique dans une fonction externe en ligne fait toujours référence au même objet." – MSalters

8

Vous éviter par:

  • Déclarant qu'il extern dans l'en-tête. Un symbole peut être déclaré n'importe quel nombre de fois.
  • Définir dans l'implémentation, une seule fois.
+0

Le problème avec ceci est que je n'ai pas de fichier d'implémentation. C'est une classe de template, donc elle ne génère pas de fichier .o. Pour cette raison, je ne fais pas de fichiers .C pour les templates. – fluffels

+0

Donc - ajoutez simplement un fichier d'implémentation (!) Cela * va * générer un fichier.o fichier, avec juste la définition unique B_SPLINE_TO_BEZIER_MATRIX dedans. – MSalters

0

Il suffit d'écrire votre fichier d'en-tête comme celui-ci

#ifndef HEADER_FILE_NAME_H

#define HEADER_FILE_NAME_H

// votre code fichier d'en-tête

#endif

cela fera en sorte qu'il ne sera pas déclaré plusieurs fois

+1

Cela aide à ne pas inclure un fichier d'en-tête deux fois au cours de la même exécution du compilateur. Mais rappelez-vous que c'est 2 fichiers source différents, donc g ++ fonctionne sur chacun d'eux séparément. – fluffels

+0

Lire attentivement la question avant de répondre. – bayda

0

des fichiers d'en-tête de Wrap (.h) dans préprocesseur conditionals pour les empêcher d'être inclus dans la table des symboles du compilateur deux fois:

#ifndef HEADER_NAME 
#define HEADER_NAME 
// code... 
#endif//HEADER_NAME 

HEADER_NAME peut vraiment être quelque chose, mais il est préférable de s'assurer que c'est quelque chose lié au fichier pour éviter plus de collisions, car cela ne fait que définir une macro préprocesseur vide (qui se retrouve également dans la table des symboles).

+0

Lisez attentivement la question avant de répondre. – bayda

+0

Cela aide à ne pas inclure un fichier d'en-tête deux fois au cours de la même exécution du compilateur. Mais rappelez-vous que c'est 2 fichiers source différents, donc g ++ fonctionne sur chacun d'eux séparément. – fluffels

+0

Ah, compréhension à la lecture ftw. J'irais personnellement avec statique dans ce cas. –

Questions connexes