2010-04-21 2 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

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 скомпилирован и определен во всех единицах трансляции, которые включают заголовок, нарушая правило Единого определения.

Простейший выход из него заключается в том, чтобы объявить его встроенным, чтобы он отображался в нескольких единицах компиляции и позволял компоновщику удалять избыточные копии (если они есть) позже.

Чуть более проблематичным являются статические элементы, которые должны быть объявлены внутри класса и определены (только один раз) в блоке трансляции. Для этого вы можете либо создать файл .cpp для определения этих переменных (и любой функции/метода, который вам не нужен в заголовке).