2010-04-21 74 views
0

我包括这头到我自己的一个:http://codepad.org/lgJ6KM6b
当我整理我开始象这样的错误:
奇怪的重新定义符号

 
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' 

我知道这很难在这个烂摊子看,但看重新定义正在发生。它们发生在像/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/include/g++-v4/new:105这样的文件中。新操作员如何获取有关gnuplot标题的信息?我甚至无法编辑该文件。这怎么可能呢?我甚至不知道如何开始调试。我希望我已经提供了足够的信息。我无法在一个小型项目中重现这一点。我主要是在寻找如何找出这种情况发生的技巧,以及如何追踪。

谢谢。

回答

1

看起来像你包含冲突的标题。尝试检查包含路径。它们通常在-I指令(至少在gcc中)或环境变量中定义。

+0

其实sellibitze看起来有正确答案(+1)。 – FireAphis 2010-04-21 06:59:24

3

你显然违反了“一个定义规则”。头文件中有很多定义。其中一些是类或类模板(这很好),其中一些是内联函数或函数模板(这也很好),其中一些是“普通”函数和非模板的静态成员(这不是很好)。

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 

一个定义规则说你的程序至多应包含一个实体的定义。例外是类,内联函数,函数模板,类模板的静态成员(我可能忘记了一些东西)。对于这些实体,只要相同实体的两个定义不在同一个翻译单元中,就可以存在多个定义。因此,将该头文件包含到多个翻译单元中会导致多个定义。

0

阅读编译器错误通常有帮助。你应该学会理解编译器告诉你什么。它抱怨一个符号被重新定义的事实是说你打破了一个定义规则。然后,它甚至会告诉你什么符号:

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

可以声明一个符号很多,你想在程序中的时间,但您只能一次定义它(除非它是内联)。在这种情况下,reset_plot在包含标题的所有翻译单元中被编译和定义,违反了One Definition Rule。

最简单的方法是声明它为内联,以便它可以出现在多个编译单元中,并让链接器稍后删除冗余副本(如果有的话)。

稍微有点问题的是必须在类中声明并且在翻译单元中定义(仅一次)的静态成员。为此,您可以创建一个.cpp文件来定义这些变量(以及任何不需要标头内联的函数/方法)。