2010-04-21 98 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文件來定義這些變量(以及任何不需要標頭內聯的函數/方法)。