«Множественное определение» ошибки компилятора C ++ - PullRequest
15 голосов
/ 26 марта 2009

Я не могу избавиться от этих, казалось бы, случайных ошибок компиляции в одном из моих классов. Я получаю около 4 ошибок, таких как:

multiple definition of `draw_line(float, float, float, float)'

и

multiple definition of `near_far_clip(float, float, float*, float*, float*, float*, float*, float*)'

помечены в середине метода.

Я также последовательно получаю multiple definition of `stack' в середине другого метода. stack - это глобальная переменная в совершенно другом файле. Это даже не упоминается в файле, в котором я получаю сообщение об ошибке.

Я попытался разделить подверженный ошибкам файл на файлы .h и .cpp (изначально был просто .cpp), и ничего об ошибке не изменилось ...

У меня нет дублирующих методов. У меня есть только один #include строк.h, и в начале есть предложение #ifndef. Все эти ошибки появляются в файле .cpp.

Есть идеи, что бы это могло быть?

Хорошо, я получил код:

lines.cpp - это конвертированный файл .c, который я получил от своего инструктора. Я включил make-файл на всякий случай, потому что у меня всегда есть проблемы с ним. Я также аннотировал, где именно ошибки отмечены в файле, но они кажутся довольно случайными, поэтому я не знаю, особенно ли это важно. Я отказался от файла .h, потому что он ничего не решал и не помогал. Я верю, что без нее легче будет найти ошибку.

Вот запрашиваемый файл main.cpp (нет .h).


Я переделал файл lines.h из-за того, что все еще получаю:

multiple definition of `draw_line(float, float, float, float)'

и

multiple definition of `near_far_clip(float, float, float*, float*, float*, float*, float*, float*)'

ошибки в файле lines.cpp, но ошибка multiple definition of `stack' теперь находится в случайном месте в файле ThreeD.cpp (и теперь помечена комментарием). Обновление: Эта ошибка была исправлена, и файлы были исправлены, чтобы показать это:

Я возился с маркировкой некоторых глобальных переменных extern, но, похоже, это ни на что не влияло.

Ответы [ 9 ]

34 голосов
/ 26 марта 2009

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

Для вашей глобальной переменной вам нужно использовать ключевое слово extern в заголовочном файле. В противном случае каждый объектный файл экспортирует свою собственную переменную, и компоновщик не понимает, какая из них правильная.

14 голосов
/ 26 марта 2009

Почему вы #include lines.cpp в ThreeD.cpp? Это очень необычно.

Ваш make-файл требует lines.o, так что вы собираетесь скомпилировать lines.cpp. Все, что определено в lines.cpp, будет в lines.o, а также в ThreeD.o.

В lines.cpp есть интригующий комментарий:

Don't forget to put declarations in your .h files. 

Я думаю, что инструктор хочет, чтобы вы разбили lines.cpp на .h и .cpp.

Выдержка из файла lines.cpp:

/* These go in your .h file or in lines.h */
/*

Line drawing header.

*/


void draw_line(float, float, float, float);
int near_far_clip(float, float, float *, float *, float *, float *,
                  float *, float *);

Я подозреваю, что эти два объявления - единственное, что должно быть в строках.h.

3 голосов
/ 26 марта 2009

Как уже было сказано - здесь недостаточно информации для правильной диагностики.

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

Это может произойти, если вы используете #defined макрос INLINE, который приходит из системного заголовка, который был забыт или удален, и по любой причине INLINE преобразуется в ничто.

например:.

//Lines.h

#define GCCC //Note the typo

#if defined(GCC)
#define INLINE inline
#elif defined (MSVC)
#define INLINE __inline
#else

#define INLINE //Due to the typo, INLINE will be turned into nothing
#endif

INLINE void draw_line(float x1, float y1, float x2, float y2)
{
   //Draw the line
}

//File1.cpp
#include "lines.h" //will define draw_line

//File2.cpp
#include "lines.h" //will also define draw_line

А связывание File1.cpp и File2.cpp приведет к нескольким ошибкам объявления

3 голосов
/ 26 марта 2009

Проверка включает охранников на орфографические ошибки.
Проверьте параметры make, может быть, кто-то скомпилирован в несколько объектных файлов.
Старайтесь исключать части файлов и кода, пока не найдете причину ошибок.

РЕДАКТИРОВАНИЕ:
исправить, включить * .cpp файлы. Они должны быть связаны.

3 голосов
/ 26 марта 2009

Пожалуйста, отправьте некоторые фрагменты кода. Может быть, вы определяете свои методы как в объявлении класса, так и вне его?

class X {
    void foo();    // No definition, just declaration
    void bar() {}  // Declaration + definition
};

void X::foo() {}    // First Definition, OK
void X::bar() {}    // Already defined, ERROR
2 голосов
/ 15 августа 2016
#ifndef THREED_H_
#define THREED_H_
#endif /* THREED_H_ */

удалите или прокомментируйте эти строки, и это сработало для меня

1 голос
/ 26 марта 2009

Не видя код, вам действительно ничто не поможет. Компилятор явно заявляет о вас противоположно (там равно хотя бы одному повторному определению).

Попробуйте воспроизвести ошибку с минимальным примером. Вы пытались скомпилировать код вне Eclipse в командной строке? С каким результатом?

1 голос
/ 26 марта 2009

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

0 голосов
/ 09 июня 2009

Привет, Что я вижу здесь, что основное правило применимо к ll. Я объясню, как работают эти ошибки и как они возникают: Давайте возьмем один пример «Создание глобальной переменной»

Не путайте заголовочный файл для файла cpp. Заголовок только там, чтобы позволить нескольким файловым проектам иметь общий интерфейс перед установкой ссылки.

1. Список элементов

Вы должны предоставить информацию о глобальной переменной в заголовке:

extern int Var_Global;

  1. Элемент списка

    while keeping the Actual code in the
    cpp :
    
    int Var_Global;
    

И убедитесь, что вы 1. включили заголовок и 2. связали код.

Свяжите код один раз, и только один раз, и есть только одна копия данных, как бы вы ни включали заголовки весь день, это говорит другому коду во время ссылки будет копия данных.

Я вижу много людей, помещающих код в заголовочные файлы, хотя это может сработать в в некоторых случаях это вредная привычка, и это может вызвать проблемы раньше или позже.

С уважением,

Prashanta

...