Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

invalid use of incomplete type / forward declaration

I tried to look at the similar problems listed here on Stackoverflow and on Google but they deal mostly with templates and that's not my case. I'm using GCC 4.4.5 on Debian Testing 64bit.
So, I have two classes - CEntity:

#ifndef CENTITY_H_INCLUDED
#define CENTITY_H_INCLUDED

#include "global_includes.h"

// game
#include "CAnimation.h"
#include "Vars.h"
#include "vector2f.h"
#include "Utils.h"

class CAnimation;

class CEntity
{
public:
    CEntity();
    virtual ~CEntity();

    void _update(Uint32 dt);

    void updateAnimation(Uint32 dt);

    void addAnimation(const std::string& name, CAnimation* anim);
    void addAnimation(const std::string& name, const CAnimation& anim);
    void removeAnimation(const std::string& name);
    void clearAnimations();

    bool setAnimation(const std::string& name);

    SDL_Surface* getImage() const;

    const vector2f& getPos() const;
    const vector2f& getLastPos() const;
    F getX() const;
    F getY() const;
    F getLastX() const;
    F getLastY() const;
    SDL_Rect* getHitbox() const;
    SDL_Rect* getRect() const;

    F getXSpeed() const;
    F getYSpeed() const;

    void setPos(const vector2f& pos);
    void setPos(F x, F y);
    void setPos(F n);
    void setX(F x);
    void setY(F y);

    void setHitboxSize(int w, int h);
    void setHitboxSize(SDL_Rect* rect);
    void setHitboxWidth(int w);
    void setHitboxHeight(int h);

    void setSpeed(F xSpeed, F ySpeed);
    void setXSpeed(F xSpeed);
    void setYSpeed(F ySpeed);

    void stop();
    void stopX();
    void stopY();

    void affectByGravity(bool affect);

    void translate(const vector2f& offset);
    void translate(F x, F y);

    bool collide(CEntity& s);
    bool collide(CEntity* s);

protected:
    CAnimation* mCurrentAnimation;
    SDL_Surface* mImage;

    vector2f mPos;
    vector2f mLastPos;
    SDL_Rect* mHitbox; // used for collisions
    SDL_Rect* mRect; // used only for blitting

    F mXSpeed;
    F mYSpeed;

    bool mAffByGrav;

    int mHOffset;
    int mVOffset;

private:
    std::map<std::string, CAnimation*> mAnims;
};

#endif // CENTITY_H_INCLUDED

and CPlayerChar which inherits from CEntity:

#ifndef CPLAYERCHAR_H_INCLUDED
#define CPLAYERCHAR_H_INCLUDED

#include "global_includes.h"

// game
#include "CEntity.h"

class CEntity;

class CPlayerChar : public CEntity
{
public:
    CPlayerChar();
    virtual ~CPlayerChar();

    virtual void update(Uint32 dt) = 0;

    virtual void runLeft() = 0;
    virtual void runRight() = 0;
    virtual void stopRunLeft() = 0;
    virtual void stopRunRight() = 0;

    virtual void attack() = 0;
    virtual void stopAttack() = 0;

    virtual void attack2() = 0;
    virtual void stopAttack2() = 0;

    virtual void ground() = 0;
    virtual void midair() = 0;

    void jump();
    void stopJump();

protected:
    // looking right?
    bool mRight;

    bool mJumping;
    bool mOnGround;
    bool mGrounded;
};

#endif // CPLAYERCHAR_H_INCLUDED

When I try to compile it, GCC throws this error:

CPlayerChar.h:12: error: invalid use of incomplete type ‘struct CEntity’
CPlayerChar.h:9: error: forward declaration of ‘struct CEntity’

I tried it first without the forward declaration 'class CEntity;' in CPlayerChar.h on line 9, but then it would throw this instead

CPlayerChar.h:12: error: expected class-name before ‘{’ token

So the forward declaration has to be there. Also, CEntity is clearly a class, not a struct.

like image 543
rivon Avatar asked Aug 08 '11 21:08

rivon


People also ask

What is a forward declaration in C++?

Forward Declaration refers to the beforehand declaration of the syntax or signature of an identifier, variable, function, class, etc. prior to its usage (done later in the program). Example: // Forward Declaration of the sum() void sum(int, int); // Usage of the sum void sum(int a, int b) { // Body }

What is forwarding declaration?

In computer programming, a forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.

When can you use forward declaration?

You will usually want to use forward declaration in a classes header file when you want to use the other type (class) as a member of the class. You can not use the forward-declared classes methods in the header file because C++ does not know the definition of that class at that point yet.

Why should I use forward declarations?

A forward declaration allows us to tell the compiler about the existence of an identifier before actually defining the identifier. In the case of functions, this allows us to tell the compiler about the existence of a function before we define the function's body.


2 Answers

You have a circular inclusion in your header files.
But without all the header files we will not be able to fix it.

I would start here.

#include "CAnimation.h"

Looking at your header you don't actually need this. You only use CAnimation by reference or pointer so the forward declaration you have should be sufficient. Move the include into the source file (ie out of the header).

The next place I would look is:

#include "global_includes.h"

Any global includes that are included in a header file better be very simple. Should only contain simple types and not include any other header files (unless they are just as simple). Anything complex is going to lead to problems with circular dependencies.

General rule of thumb

A header file should only include header files that it absolutely needs. Otherwise they should be included from the source file. You only absolutely need a header file if it defines a class that is used as a parent class you have members objects of that class, or you use parameter objects of that class.

I use the term object to distinguish from references or pointers. If you are using these you do not need to include the header file. You only need to do a forward declaration.

like image 148
Martin York Avatar answered Oct 08 '22 11:10

Martin York


You probably have got a loop in your includes in such way that CPlayerChar doesnt know who really is CEntity, it just knows that it exists, but doesnt know what is it.

If you remove the "class CEntity" declaration, you will see that GCC will complain that CEntity doesnt exists.

You must check that nothing that CEntity includes include CPlayerChar.

like image 38
André Puel Avatar answered Oct 08 '22 11:10

André Puel