C++ 不完整类型/前向声明的无效使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6988924/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
invalid use of incomplete type / forward declaration
提问by rivon
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:
我试图查看 Stackoverflow 和 Google 上列出的类似问题,但它们主要处理模板,这不是我的情况。我在 Debian 测试 64 位上使用 GCC 4.4.5。
所以,我有两个类 - 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:
和继承自 CEntity 的 CPlayerChar:
#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:
当我尝试编译它时,GCC 抛出此错误:
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
我在没有前向声明“class CEntity;”的情况下首先尝试了它 在第 9 行的 CPlayerChar.h 中,但随后它会抛出这个
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.
所以前向声明必须在那里。此外,CEntity 显然是一个类,而不是一个结构。
回答by Martin York
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).
看看你的标题,你实际上并不需要这个。您只能通过引用或指针使用 CAnimation,因此您拥有的前向声明应该就足够了。将包含移动到源文件中(即从头文件中移出)。
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.
我用这个词object
来区别引用或指针。如果您正在使用这些,则不需要包含头文件。你只需要做一个前向声明。
回答by André Puel
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.
您的包含中可能有一个循环,以至于 CPlayerChar 不知道 CEntity 到底是谁,它只知道它存在,但不知道它是什么。
If you remove the "class CEntity" declaration, you will see that GCC will complain that CEntity doesnt exists.
如果删除“class CEntity”声明,您将看到 GCC 会抱怨 CEntity 不存在。
You must check that nothing that CEntity includes include CPlayerChar.
您必须检查 CEntity 包含的任何内容是否包含 CPlayerChar。
回答by Kerrek SB
You have to ensure that the full definitionof the class CEntity
is visible at the point where you define the class CPlayerChar
. (So check your inclusions.)
您必须确保在您定义类的地方可以看到类的完整定义。(所以检查你的内含物。)CEntity
CPlayerChar
This is because you can only inherit from fully defined classes, but not from just forward-declared ones.
这是因为您只能从完全定义的类继承,而不能从前向声明的类继承。
The only time you can get away with forward-declarations in place of full definitions is when you make pointers or references to a type, but only if you never access any of its members, or (thanks to @Alf) when declaring a function with incomplete return type.
唯一可以使用前向声明代替完整定义的时间是当您对类型进行指针或引用时,但前提是您从不访问其任何成员,或者(感谢@Alf)在声明函数时不完整的返回类型。