C++ c++;基类未定义。在另一个类中包含基和子类

C++ c++;基类未定义。在另一个类中包含基和子类,c++,inheritance,C++,Inheritance,我有一个类GameObject,它有一个分量和变换向量。 转换是一个组件,但可以自己访问。 当我试图在GameObject中同时包含Component.h和Transform.h时,组件上出现了一个基类未定义错误 错误消息: Error 1 error C2504: 'Component' : base class undefined c:\users\pyro\documents\visual studio 2010\projects\engine\main\transform

我有一个类GameObject,它有一个分量和变换向量。 转换是一个组件,但可以自己访问。 当我试图在GameObject中同时包含Component.h和Transform.h时,组件上出现了一个基类未定义错误

错误消息:

    Error   1   error C2504: 'Component' : base class undefined c:\users\pyro\documents\visual studio 2010\projects\engine\main\transform.h 9
GameObject.h

    #ifndef _GameObject
    #define _GameObject
    #include "Core.h"
    #include "Component.h"
    #include "Transform.h"

    class Transform;
    class Component;

    class GameObject
    {
        protected:
            Transform* transform;
            vector<Component*> components;
    };

    #endif
转换.h

    #ifndef _Transform
    #define _Transform

    #include "Core.h"
    #include "Component.h"

    //Base class undefined happens here
    class Transform : public Component
    {
    };

    #endif
我发现了很多其他的话题,但它们并没有真正解决我的问题。
因此,问题是:为什么会出现此错误以及如何修复它?

您的代码有几个问题:


1.循环依赖
GameObject.h
包括
Component.h
,而
Component.h
包括
GameObject.h

这种循环依赖打破了一切。根据您“从哪个文件开始”的不同,
GameObject
Component
中将不可见,反之亦然,这是由于包含保护

删除循环依赖项:您根本不需要那些
#include
s,因为您已经在使用前向声明。
一般来说,尽量减少在标题中使用
#include


2.语法错误 修复后,添加缺少的
}位于
组件.h

(您对
Transform
的定义认为它是
Component
中的一个嵌套类,此时尚未完全定义该类。)


3.保留名称
这在今天可能不会给您带来实际问题,但您的宏名称不应以
开头,因为它们是为实现(编译器)使用而保留的。

假设某些源文件具有
#include“Component.h”
指令,而没有其他
#include
指令。以下是发生的情况,顺序如下:

  • 定义了预处理器符号
    \u组件
  • 扩展了
    组件.h
    中的
    #include“GameObject.h”
    指令
  • GameObject.h
    中的
    #include“Component.h”
    指令已展开。
    这不起任何作用,因为现在已定义了组件
  • 扩展了
    GameObject.h
    中的
    #include“Transform.h”
    指令
  • Transform.h
    中的类
    Transform
    的定义将无法编译,因为基类
    组件
    尚未定义

  • 问题是您有太多多余的
    #include
    语句。例如,
    GameObject.h
    不需要包含
    Component.h
    。所需要的只是远期申报。通常,除非您确实需要,否则不要将文件包含在头中。如果您确实需要这样做,您需要非常小心圆形包含。

    请注意GameObject.h和Component.h都包含彼此。这往往会导致奇怪的行为,在您需要定义时,并非所有定义都可见。你可能想把它看成是真正的根本原因。标题符是否在 Cyr.H./Cuth>??JARDDC:从所显示的标题中使用的名称来看,我认为它不太可能使用允许使用的名称:它们都践踏了C++编译器及其标准库的实现的名称……详述迪特玛所说的:不要使用以下划线开头的名称;不要在任何地方使用带有双下划线的名称。(实际的规则比这更细微,但遵循这两个简单的规则永远不会引起问题)来扩展Dietmar和R.Martinho Fernandes所说的:使用前导下划线的这种普遍做法的出现是因为系统头文件使用的是前导下划线:如果这是C++专家如何做的事情,那肯定是正确的事情,对不对?这些系统标题使用领先的下划线,因为如果你遵循不使用领先下划线的规则,他们的名字不会与你的冲突。1。应该行得通,而且我已经在代码中的许多其他地方使用过它,而且没有中断。2.已修复。3.知道这一点很好。我将修复它。@Matthew:不,它不应该。:)预处理器不智能,当然也无法知道你的include guards“是什么意思“
    #include
    是一种简单的文本替换,如果你试图手动扩展指令,你会很快明白我在说什么。@Matthew:如果你想赢得一场模糊编程竞赛,循环和递归包含是个好主意。否则他们会给你带来麻烦,就像他们在这里一样。@Matthew:re“2.已经修复。在发布的代码中丢失的右括号只是一个剪切粘贴错误吗?@Johnsyweb:Forward声明不是一种设计味道。
        #ifndef _Transform
        #define _Transform
    
        #include "Core.h"
        #include "Component.h"
    
        //Base class undefined happens here
        class Transform : public Component
        {
        };
    
        #endif