Первое предложение
Убедитесь, что вы включили защиту заголовков в каждый заголовок для предотвращения повторного включения:
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
...whatever was in game.h before...
#endif /* GAME_H_INCLUDED */
Аналогично для каждого из других заголовков.
Этовероятно, что один из ваших заголовков включает в себя один из других, и это приводит к проблеме переопределения - потому что отсутствуют средства защиты заголовков.
Некоторые компиляторы поддерживают #pragma once
, чтобы гарантировать, что он включает только заданныйЗаголовок один раз.Если все компиляторы, которые вы когда-либо будете использовать, поддерживают его, вы можете использовать прагму вместо показанного переносимого и надежного механизма;однако вы делаете это на свой страх и риск.
Второе предложение
Нет заголовков - это озадачивает (на самом деле, «беспокойство» - это, вероятно, лучший термин для этого).Как разные файлы узнают о разных структурах?
В структуре игры я пытаюсь создать массив структур "сцены".Компилятор жалуется, говоря «переопределение структуры« scene »».
Звучит так, как будто вы должны делать что-то вроде:
struct game
{
...
struct scene { ... } *next_scene;
struct scene { ... } list_scenes[24];
...
};
Это недопустимо;как только вы определили тег структуры один раз, вы не можете переопределить его.Минимальная ревизия:
struct game
{
...
struct scene { ... } *next_scene;
struct scene list_scenes[24];
...
};
Рекомендуемая ревизия (с большим количеством предостережений, связанных с вашей организацией):
struct game
{
...
struct scene { ... };
struct scene *next_scene;
struct scene list_scenes[24];
...
};
Но этот материал действительно, действительно, принадлежит заголовку, еслинесколько исходных файлов будут использовать одну и ту же структуру;в противном случае вы нарушаете два канона кредо Agile Development (хотя на самом деле это правила «хорошего программирования» общего назначения):
- DRY: не повторяйте себя
- SPOT: Единая точка истины
Если в нескольких исходных файлах содержится определение struct game
(или struct scene
, или struct player
), то вы повторяете себя (плохо, особеннокогда вам нужно изменить определение, и уже нет единого места, где можно найти определение struct game
(или struct scene
, или struct player
).
Заголовочные файлы являются ключом к управлениюсложность разработки на C ++.
Если проблема не устранена
Если это все еще не идентифицировало вашу проблему, то будет сложно угадать, что вы сделали.Нужно показать минимальный код, который показывает проблему. Возьмите копию того файла, который терпит неудачу, и назовите новый файл minimal.cpp
(или любое новое имя с соответствующим суффиксом файла). Теперь отредактируйте minimal.cpp
. Безжалостно выброситьвсе после тОшибка, за исключением того, что необходимо для синтаксического заполнения пространств имен или структур.Это можно сделать с помощью стратегически размещенных пар #if 0
и #endif
или с помощью полноразмерных удалений.После каждого изменения сохраняйте файл, проверяйте, что вы все равно получаете ту же ошибку компиляции.Если вы закомментировали код с помощью #if 0 / #endif
, то после сбоя компиляции удалите этот блок кода (и сохраните снова и снова проверьте компиляцию).Задний материал обычно тривиален, чтобы иметь дело с;вам нужно только несколько правильно расположенных закрывающих скобок и точек с запятой.
После этого вы начинаете устранять материал до появления ошибки.Продолжайте до тех пор, пока не останется ни одной строки вашего кода, которую вы можете удалить, не теряя ошибки во время компиляции.
В этот момент, если контрольный пример меньше 40 строк, у вас есть что-то, что вы можете поместить в свой файл.вопрос.До этого вы не сделали достаточно хорошую работу.(Обратите внимание, что вам не нужны какие-либо комментарии в репродукции; это будет достаточно просто, чтобы понять без них.)
Так вы сможете отследить любую неприятную ошибку - как можно быстрее устраните как можно больше кода.оставляя вас только с неприятными вещами.