Повторные Ошибки Повторного определения от включения того же заголовка в нескольких cpps

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

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

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

15
задан Bart 19 September 2012 в 12:17
поделиться

8 ответов

Так как Вы объявляете те переменные в заголовочном файле, и включая заголовочный файл в каждом файле C++, каждый файл C++ имеет свою собственную копию их.

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

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

#ifdef MAINFILE
    #define EXTERN
#else
    #define EXTERN extern
#endif

EXTERN MYSTRUCT Job_Grunt;
EXTERN MYSTRUCT *Grunt = &Job_Grunt;
EXTERN MYSTRUCT Job_Uruk;
EXTERN MYSTRUCT *Uruk = &Job_Uruk;

Затем в один из Ваших файлов C++, добавляют a...

#define MAINFILE

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

, Конечно, реальный решение не состоит в том, чтобы использовать глобальные переменные вообще, но когда Вы только начинаете, этого трудно достигнуть.

23
ответ дан 1 December 2019 в 00:41
поделиться

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

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

Так в Вашем заголовочном файле необходимо сделать все определения предописания путем добавления extern ключевое слово.

extern MYSTRUCT Job_Grunt;
extern MYSTRUCT *Grunt;
extern MYSTRUCT Job_Uruk;
extern MYSTRUCT *Uruk;

extern int Other_data[100];

И затем в [1 110] один (и только один) Ваших исходных файлов, определяйте переменные обычно:

MYSTRUCT Job_Grunt;
MYSTRUCT *Grunt = &Job_Grunt;
MYSTRUCT Job_Uruk;
MYSTRUCT *Uruk = &Job_Grunt;

int Other_data[100];
12
ответ дан 1 December 2019 в 00:41
поделиться

Необходимо определить переменные как экстерна в заголовочном файле и затем определить их в cpp файле также. т.е.:

extern MYSTRUCT Job_Grunt;

в Вашем заголовочном файле, и затем в cpp файле в Вашем проекте объявляют их обычно.

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

4
ответ дан 1 December 2019 в 00:41
поделиться

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

объявление А объявляет о существовании объекта, но не вызывает инстанцирование. Следовательно операторы экстерна являются объявлениями - не определения.

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

Примечание: использование инстанцирования слова здесь действительно только относится к элементам данных.

6
ответ дан 1 December 2019 в 00:41
поделиться

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

, Поскольку Gerald сказал, необходимо определить ссылку на структуру (использующий 'экстерна') в заголовке и иметь один cpp файл в проекте, который инстанцирует экземпляра.

0
ответ дан 1 December 2019 в 00:41
поделиться

У меня тоже была эта проблема некоторое время назад. Позвольте мне попытаться объяснить, что решило это. У меня был файл global.h, который имел все объявления и должен был быть включен в каждый файл cpp. Вместо того, чтобы включать его в каждый .cpp, я включил его в .h. Во все мои файлы ".h" я добавил строки #ifndef и #define и закончил #endif. Это решило проблему MD. Надеюсь, что это работает и для вас.

0
ответ дан 1 December 2019 в 00:41
поделиться

GCC 3.4 и поддерживает #pragma once. Просто помещенный #pragma once наверху Вашего кода вместо использования включают защиту. Это может или не может быть более успешным, но это стоит того, чтобы попытаться. И не, это не (всегда) точно эквивалентно включать защите.

-3
ответ дан 1 December 2019 в 00:41
поделиться

This is what worked for me: linking the sources into separate libraries. (My problem was not with creating a program but one/many libraries.) I then linked (successfully) one program with the two libraries I created.

I had two sets of functions (with one depending on the other) in the same source file, and declared in the same single header file. Then I tried to separate the two function sets in two header+source files.

I tried with both #pragma once and include guards with #ifndef ... #define ... #endif. I also defined the variables and functions as extern in the header files.

As Steve Fallows pointed out, the problem isn't with the compilation but rather with linkage. In my particular problem, I could get away with having two sets of functions, each in its own source file, compiling and then linking into two separate libraries.

g++ -o grandfather.o -c grandfather.cpp
g++ -o father.o -c father.cpp
g++ -fPIC -shared -o libgf.so grandfather.o
g++ -fPIC -shared -o libfather.so father.o

This forces me to link my programs with both libgf.so and libfather.so. In my particular case it makes no difference; but otherwise I couldn't get them to work together.

0
ответ дан 1 December 2019 в 00:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: