2010-04-21 6 views
0

J'inclus cet en-tête dans un de mes propres: http://codepad.org/lgJ6KM6b
Quand je compilé j'ai commencé à obtenir des erreurs comme ceci:
étranges symboles redéfinis

 
CMakeFiles/bin.dir/SoundProjection.cc.o: In function `Gnuplot::reset_plot()': 
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/include/g++-v4/new:105: multiple definition of `Gnuplot::reset_plot()' 
CMakeFiles/bin.dir/main.cc.o:project/gnuplot-cpp/gnuplot_i.hpp:962: first defined here 
CMakeFiles/bin.dir/SoundProjection.cc.o: In function `Gnuplot::set_smooth(std::basic_string, std::allocator > const&)': 
project/gnuplot-cpp/gnuplot_i.hpp:1041: multiple definition of `Gnuplot::set_smooth(std::basic_string, std::allocator > const&)' 
CMakeFiles/bin.dir/main.cc.o:project/gnuplot-cpp/gnuplot_i.hpp:1041: first defined here 
CMakeFiles/bin.dir/SoundProjection.cc.o:/usr/include/eigen2/Eigen/src/Core/arch/SSE/PacketMath.h:41: multiple definition of `Gnuplot::m_sGNUPlotFileName' 

Je sais qu'il est difficile de voir dans ce gâchis, mais regardez où les redéfinitions ont lieu. Ils ont lieu dans des fichiers comme /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/include/g++v4/new:105. Comment le nouvel opérateur obtient-il des informations sur un en-tête gnuplot? Je ne peux même pas éditer ce fichier. Comment cela pourrait-il être possible? Je ne suis même pas sûr de savoir comment commencer à le déboguer. J'espère avoir fourni suffisamment d'informations. Je n'ai pas pu reproduire cela dans un petit projet. Je cherche principalement des astuces pour savoir pourquoi cela se passe et comment le retrouver.

Merci.

Répondre

1

On dirait que vous incluez des en-têtes conflictuels. Essayez de vérifier vos chemins d'inclusion. Ils sont généralement définis dans la directive -I (au moins dans gcc) ou dans une variable d'environnement.

+0

En fait, sellibitze semble avoir la bonne réponse (+1). – FireAphis

3

Vous enfreignez évidemment la "règle de définition unique". Vous avez beaucoup de définitions dans votre fichier d'en-tête. Certains d'entre eux sont des classes ou des modèles de classe (ce qui est bien), certains sont des fonctions inline ou des modèles de fonctions (ce qui est également bien) et certains sont des fonctions "normales" et des membres statiques de non-templates (ce qui n'est pas bien).

class foo;  // declaration of foo 
class foo {  // definition of foo 
    static int x; // declaration of foo::x 
}; 

int foo::x;  // definition of foo::x 

void bar();  // declaration 
void bar() {} // definition 

La seule règle de définition dit que votre programme doit contenir au plus une définition d'une entité. Les exceptions sont les classes, les fonctions en ligne, les modèles de fonctions, les membres statiques des modèles de classe (j'ai probablement oublié quelque chose). Pour ces entités, plusieurs définitions peuvent exister tant que deux définitions de la même entité ne se trouvent pas dans la même unité de traduction. Ainsi, l'inclusion de ce fichier d'en-tête dans plusieurs unités de traduction conduit à plusieurs définitions.

0

La lecture des erreurs de compilation aide généralement. Vous devriez apprendre à comprendre ce que le compilateur vous dit. Le fait qu'il se plaint de la redéfinition d'un symbole signifie que vous enfreignez la règle de définition unique. Ensuite, il vous indique même ce que les symboles sont les suivants:

class GnuPlot { 
//... 
    GnuPlot& reset_plot(); // <-- declaration 
//... 
}; 
//... 
Gnuplot& Gnuplot::reset_plot() { // <-- Definition 
    nplots = 0; 
    return *this; 
} 

Vous pouvez déclarer un symbole autant de fois que vous le souhaitez dans un programme, mais vous ne pouvez définir qu'une seule fois (à moins qu'il soit inline). Dans ce cas, le reset_plot est compilé et défini dans toutes les unités de traduction qui incluent l'en-tête, en violation de la règle de définition unique. Le moyen le plus simple est de le déclarer en ligne, afin qu'il puisse apparaître dans plus d'une unité de compilation et laisser l'éditeur de liens supprimer les copies redondantes (le cas échéant) plus tard.

Un peu plus problématique sont les membres statiques qui doivent être déclarés dans la classe et définis (une seule fois) dans une unité de traduction. Pour cela, vous pouvez soit créer un fichier .cpp pour définir ces variables (et toute fonction/méthode dont vous n'avez pas besoin inline dans l'en-tête).