Множественная ошибка включения, не могу найти решение

Недавно я столкнулся с ошибками включения нескольких файлов. Я работаю над космической аркадной игрой и разделил свои классы/объекты на разные файлы .cpp, и чтобы убедиться, что все работает нормально, я создал следующий заголовочный файл:

#ifndef SPACEGAME_H_INCLUDED
#define SPACEGAME_H_INCLUDED
//Some Main constants
#define PI 3.14159265


//Standard includes
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;

//SDL headers
#include "SDL.h"
#include "SDL_opengl.h"
#include "SDL_mixer.h"
#include "SDL_image.h"

//Classes and project files
#include "Player.cpp"
#include "planet.cpp"
#include "Destructable.cpp"
#include "PowerUp.cpp"
#include "PowerUp_Speed.cpp"

#endif // SPACEGAME_H_INCLUDED

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

Однако у меня есть класс Player/Ship, который выдал мне ошибки типа «переопределение класса Ship». В конце концов я нашел обходной путь, включив команды препроцессора #ifndef и #define в файл определения класса:

#ifndef PLAYER_H
#define PLAYER_H
/** Player class that controls the flying object used for the space game */
#include "SpaceGame.h"


struct Bullet
{
  float x, y;
  float velX, velY;
  bool isAlive;
};

class Ship
{
    Ship(float sX,float sY, int w, int h, float velocity, int cw, int ch)
    {
        up = false; down = false; left = false; right = false;
        angle = 0;
....
#endif

С помощью этого обходного пути я потерял ошибки «переопределения класса/структуры», но это дало мне странные ошибки в моем файле класса PowerUp_Speed, для которого требуется класс Ship:

#include "SpaceGame.h"

class PowerUp_Speed : public PowerUp
{

    public:
        PowerUp_Speed()
        {
            texture = loadTexture("sprites/Planet1.png");
        }

        void boostPlayer(Ship &ship)
        {
            ship.vel += 0.2f;
        }
};

Я получаю следующие ошибки: "Неверное использование неполного типа "struct Ship"" и "Передовое объявление "struct ship""

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


person Joey Dewd    schedule 17.06.2012    source источник


Ответы (1)


Обычно файлы cpp не включаются.
Вам нужно включать только заголовочные файлы!

Когда вы включаете файлы cpp, вы в конечном итоге нарушаете правило одного определения (ODR). .
Обычно ваши заголовочные файлы (.h) определяют класс/структуры и т. д., а ваши исходные файлы (.cpp) определяют функции-члены и т. д.
Согласно ODR у вас может быть только определение для каждой переменной/функции и т. д., в том числе один и тот же файл cpp в нескольких файлах создает более одного определения и, следовательно, нарушает ODR.

Как это сделать?

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

Как насчет предварительных объявлений?

Всегда предпочтительнее использовать классы или структуры с предварительным объявлением вместо включения файлов заголовков, что дает значительные преимущества, например:

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

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

person Alok Save    schedule 17.06.2012
comment
Большое спасибо, что нашли время все записать. Я был немного не уверен в том, как на самом деле следует использовать заголовки в многофайловых проектах, но теперь все ясно. Мне придется немного переделать мой проект, чтобы убедиться, что все аккуратно и организовано с несколькими файлами заголовков, и я опубликую свои результаты здесь. - person Joey Dewd; 17.06.2012
comment
Хорошо, мне потребовалось некоторое время, чтобы переработать весь мой код, но, наконец, мне удалось снова заставить все работать. На этот раз все немного более организовано и отлично работает в нескольких файлах. Еще раз спасибо за помощь, Алс! - person Joey Dewd; 18.06.2012
comment
@JoeyDewd: рад помочь :) - person Alok Save; 18.06.2012