Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple inclusion error, can't find a solution

I've recently been struggling with multiple file inclusion errors. I'm working on a space arcade game and have divided my classes/objects into different .cpp files and to make sure everything still works fine together I have build the following header file:

#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

And at the top of every one of my files I included (only) this header file which holds all .cpp files and the standard includes.

However, I have a Player/Ship class that has given me errors of the 'redefinition of Ship class' type. I eventually found a workaround by including preprocessor #ifndef and #define commands in the class definition file:

#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

With this workaround I lost the 'class/struct redefinition' erorrs but it gave me weird errors in my class file PowerUp_Speed that requires the Ship class:

#include "SpaceGame.h"

class PowerUp_Speed : public PowerUp
{

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

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

I've been getting the following errors: 'Invalid use of incomplete type 'struct Ship'' and 'Forward declaration of 'struct ship''

I believe the origin of these errors is still in my trouble with the multiple file inclusion errors. I described every step I took in order to reduce my amount of errors but so far none of all the posts I've found on Google helped me so that's why I'm politely asking if any of you could help me find the origin of the problems and a fix.

like image 334
Joey Dewd Avatar asked Jan 16 '23 09:01

Joey Dewd


1 Answers

Usually, You do not include cpp files.
You need to only include the header files!

When you include cpp files, You end up breaking the One Definition Rule(ODR).
Usually, Your header files(.h) will define the class/structures etc and your source(.cpp) files will define the member functions etc.
As per ODR you can have only definition for each variable/function etc, including the same cpp file in multiple files creates more than one definition and hence breaks the ODR.

How should you go about this?

Note that to be able to create objects or call member functions etc, All you need to do is include the header file which defines that class in the source file which needs to create the object etc. You don't need to include source files anywhere.

What about Forward Declarations?

It is always preferred to use forward declaring classes or structures instead of including the header files, doing so has significant advantages, like:

  • Reduced compilation time
  • No Pollution of global namespace.
  • No Potential clash of preprocessor names.
  • No Increase in Binary size(in some cases though not always)

However, Once you forward declare a type you can only perform limited operations on it because the compiler sees it as an Incomplete Type. So You should try to Forward declarations always but you can't do so always.

like image 193
Alok Save Avatar answered Jan 29 '23 09:01

Alok Save