C++ C++;类继承混淆

C++ C++;类继承混淆,c++,inheritance,C++,Inheritance,当包含所有相关的头时,为什么会出现“error C2504:‘CEntity’:基类未定义”错误 我有一个CMap,它可以完成大部分重物搬运: // CMap.h #ifndef _CMAP_H_ #define _CMAP_H_ #include "CEntity.h" class CMap { public: CMap(void); void OnLoad(); void OnRender(); std::vector&

当包含所有相关的头时,为什么会出现“error C2504:‘CEntity’:基类未定义”错误

我有一个CMap,它可以完成大部分重物搬运:

// CMap.h
#ifndef _CMAP_H_
#define _CMAP_H_
#include "CEntity.h"
class CMap {
    public:
        CMap(void);
        void OnLoad();
        void OnRender();
        std::vector<CTile*> TileList;
};
#endif
还有各种各样的百岁儿童:

// CEntity_Buggy.h
#ifndef _CENTITY_BUGGY_H_
#define _CENTITY_BUGGY_H_
#include "CEntity.h"
class CEntity_Buggy : public CEntity {
    public:
        CEntity_Buggy(void);    
};
#endif
现在,我的主地图加载例程可以正常工作,渲染路由也可以正常工作,它恰好需要查看瓷砖以获取一些信息:

// CMap.cpp
#include "CMap.h"

void CMap::OnLoad() {
    ...
}

void CMap::OnRender() {
    /* here would be some rendering code ... */

    std::vector<CTile*>::iterator i;
    for (i=this->TileList.begin(); i!=this->TileList.end(); ++i) {
        CTile* tile = *i;

        for(unsigned int i = 0; i < tile->EntityList.size(); i++) {
            label[0] = tile->EntityList[i]->Label[0];
        }
    }
}
现在我得到了很多
\centity_buggy.h(18):错误C2504:“centity”:基类未定义的错误,但我不确定原因。我的百分马车.h包括百分之.h

当前的完整版本(这是第一个C++项目,所以它有很大的缺陷)是,如果这有帮助的话。

取出非标准的pragma一次,然后进行完整的重建

是否在Visual Studio中打开了预编译头?这是一个构建时错误陷阱

仅包含一次的便携式方法是

#ifndef IDENTIFIER
#define IDENTIFIER

// header contents

#endif
IDENTIFIER
是根据标题名选择的,如果您很聪明,可以添加一些额外的字符,以减少与任何内容冲突的可能性。例如,
CENTITY_H_4D59_3FC4
(随机选择的十六进制数字)

一个好的编译器(例如,
gcc
)能够识别这种“ifdef仪式”,实际上不会读取头,因此它的效率与
#pragma once
一样高

我写这篇文章是因为,显然,
centity.h
头定义了
centity
类,它被包含在派生类
CEntityBuggy
定义的正上方。那么为什么它不定义类呢?可能是
#pragma once
有缺陷并吃掉了头,或者编译器正在从预编译头缓存中反刍一些过时的头材料

像这样的构建时的东西会让你对正确的代码摸不着头脑。

去掉非标准的pragma一次,然后进行完整的重建

是否在Visual Studio中打开了预编译头?这是一个构建时错误陷阱

仅包含一次的便携式方法是

#ifndef IDENTIFIER
#define IDENTIFIER

// header contents

#endif
IDENTIFIER
是根据标题名选择的,如果您很聪明,可以添加一些额外的字符,以减少与任何内容冲突的可能性。例如,
CENTITY_H_4D59_3FC4
(随机选择的十六进制数字)

一个好的编译器(例如,
gcc
)能够识别这种“ifdef仪式”,实际上不会读取头,因此它的效率与
#pragma once
一样高

我写这篇文章是因为,显然,
centity.h
头定义了
centity
类,它被包含在派生类
CEntityBuggy
定义的正上方。那么为什么它不定义类呢?可能是
#pragma once
有缺陷并吃掉了头,或者编译器正在从预编译头缓存中反刍一些过时的头材料


像这样的构建时东西会让你对外观正确的代码摸不着头脑。

我怀疑,这里的具体原因包括:

  • 百分之h包括CCamera.h
  • CCamera.h包括CMap.h
  • CMap.h包括CEntity_四轮马车.h
所以CEntity.h导致CEntity_Buggy.h在CEntity被定义之前被包括在内。在这种情况下,它看起来不像CMap.h真的需要CEntity_Buggy.h-您可能只需要将其包含在cpp中


一般来说,尽可能避免在.h文件中包含。转发声明是您的朋友:)

我想,这里的具体原因包括:

  • 百分之h包括CCamera.h
  • CCamera.h包括CMap.h
  • CMap.h包括CEntity_四轮马车.h
所以CEntity.h导致CEntity_Buggy.h在CEntity被定义之前被包括在内。在这种情况下,它看起来不像CMap.h真的需要CEntity_Buggy.h-您可能只需要将其包含在cpp中


一般来说,尽可能避免在.h文件中包含。转发声明是你的朋友:)

你忘了在类定义的末尾加一个分号吗?对不起,这是在示例代码中-我现在已经更新了。你是用小写形式写头文件名,比如
centity_buggy.h
,但包括大写形式的头文件名,比如
#include“centity_buggy.h”
?如果这段代码从未从Windows移植出去,这可能无关紧要,但在区分大小写的文件系统上,您会感到痛苦。(这可能不是问题;只是一个旁注。)是的,我现在在Windows上,但从我的黑白旧网络开发时代起,我养成了区分大小写的习惯:)我评论说,包括你的CMap.h中的“CEntity_Buggy.h”,它对我来说很好。我现在要更仔细地看一下。你忘了在类定义的末尾加一个分号吗?对不起,这是在示例代码中-我现在已经更新了它。你是用小写写头文件名,比如
centity_buggy.h
,但要用大写写头文件名,比如
#include“centity_buggy.h”
?如果这段代码从未从Windows移植出去,这可能无关紧要,但在区分大小写的文件系统上,您会感到痛苦。(这可能不是问题;只是一个旁注。)是的,我现在在Windows上,但从我的黑白旧网络开发时代起,我养成了区分大小写的习惯:)我评论说,包括你的CMap.h中的“CEntity_Buggy.h”,它对我来说很好。我现在要仔细看一下。即使条件为false,编译器也必须读取ifdef中的代码,因为它可能包含语法错误。我已经检查了设置,“预编译头”似乎已关闭。将所有的
#pragma once
更改为“标准”守卫并没有什么区别——尽管我也没想到,
#pragma once
并不完全是晦涩难懂的伏都教。介绍了
#pragma的优点和缺点一次
,但在这种情况下,我认为您会看到基于
#define
的include-guard的相同结果。@Dani:当然
gcc
re
// CMap.h
#include "CEntity_Buggy.h" // add this to the header

// CMap.cpp
#include "CMap.h"

void CMap::OnLoad() {
    CEntity_Buggy buggy;
    buggy.OnLoad();
}
#ifndef IDENTIFIER
#define IDENTIFIER

// header contents

#endif