C++ &引用;“不完整类型的无效使用”;在基本的猎人/猎物训练中

C++ &引用;“不完整类型的无效使用”;在基本的猎人/猎物训练中,c++,C++,因此,我目前的任务是做一个基本的猎人和猎物模拟,在讨论了其他几个问题之后,我的教授建议我现在就把所有的东西都放在main.cpp中,让它真正工作起来 我当前的问题是,在bioture::Find()函数中,它声称Grid类是不完整的,即使它预先声明在文件的顶部。我最初的想法是将网格类放在生物之前,但这会导致更多或相同的错误(指生物不完整),因为网格本质上是一个生物指针的2D数组。下面是相关的位代码,整个文件可以在Dropbox上找到 类网格;//**错误:“类网格”的转发声明 //其他东西。。

因此,我目前的任务是做一个基本的猎人和猎物模拟,在讨论了其他几个问题之后,我的教授建议我现在就把所有的东西都放在
main.cpp
中,让它真正工作起来

我当前的问题是,在
bioture::Find()
函数中,它声称
Grid
类是不完整的,即使它预先声明在文件的顶部。我最初的想法是将
网格
类放在
生物
之前,但这会导致更多或相同的错误(指
生物
不完整),因为
网格
本质上是一个
生物
指针的2D数组。下面是相关的位代码,整个文件可以在Dropbox上找到


类网格;//**错误:“类网格”的转发声明
//其他东西。。。
阶级生物
{
公众:
网格*网格;
坐标位置;
内继代繁殖;
内斯特芬格;
焦面;
布尔搬家了;
生物(网格*\u网格,坐标位置,字符脸)//构造器
{
网格=_网格;
位置=_位置;
面=_面;
Stepfride=Stephanger=0;
hasMoved=false;
}
vector Find(char thisFace)//返回被捕食的coords列表
{
矢量结果;

对于(int i=position.x-1;i您有一个循环依赖关系(我似乎记得您以前有过这个问题)。将内容放在同一个文件中并不能真正解决问题(尽管可能有助于您更清楚地看到问题).您需要做的是正确地排序,以便每个函数都在它需要的类之后定义

在这种情况下,我会这样做

class Grid;

class Creature
{
public:
    Grid* theGrid;
    ...
    vector<Coords> Find(char thisFace);
    ...
};

class Grid
{
public:
    Creature* grid[MAX_X][MAX_Y];
    ...
};

vector<Coords> Creature::Find(char thisFace)
{
   ...
}
类网格;
阶级生物
{
公众:
网格*网格;
...
向量查找(char thisFace);
...
};
类网格
{
公众:
生物*网格[MAX_X][MAX_Y];
...
};
向量生物::查找(char thisFace)
{
...
}
生物::Find
需要
生物
类(显然)和
网格
类,因此必须在这两个类都已完全定义之后进行


如果您最终将
生物::Find
定义放在头文件中,则必须添加
inline
关键字,否则您将获得多个定义。

前向声明可以声明指针。但是编译器还不知道前向声明的类包含什么。因此,您不能期望它将w差不多

class Grid;
//
theGrid->Occupant(temp)


您需要包含包含Grid的整个定义的文件。或者您可以将
生物::find
函数的定义移动到包含Grid.h的另一个文件中。例如,在
Grid.cpp

中是的,很抱歉为类似主题提出了一个新问题,我不确定它是否正确它。我在各种函数上得到了未解决的外部结果,教授也不明白为什么,这就是为什么他让我把它全部放在主要部分。我认为网格的预声明应该防止这样的事情,还是只对定义有效?@Farlo No,预声明(通常称为前向声明)告诉编译器网格是一个类,因此(例如)
Grid*theGrid;
是合法的。但是转发声明不会告诉编译器关于该类的任何信息。因此
即使在转发声明之后也是不合法的,因为转发声明不会告诉编译器网格有一个名为Occupant@Farlo通过确保使用不完整类型的代码的实现遵循完成类型的声明,通常可以避免一个问题将
bioture::Find
方法的实现移出类(仅将其声明为成员,不在类中实现)然后在答案上的
网格的正式定义和+1之后实现它。啊,这是有意义的。我假设这就是原因,除了整洁之外,类被拆分为头文件和cpp文件?如果我决定将所有内容拆分为单独的文件,你能想到任何原因吗?即使你也无法解决外部问题gh功能“标题”相同(当然还有范围解析运算符)?编辑:@WhozCraig感谢您的评论,不幸的是,在我获得一些声誉之前,我不能+1,否则我会的。我们在这里看到,在被分成多个文件的项目中,最常见的原因是人们忘记编译他们需要的所有文件。我想另一个可能的原因是decl不一致不同文件中的参数和定义。我没有立即想到其他任何事情。我认为你教授的建议很好,让它在一个文件中工作。然后,如果你想的话,逐渐将它移回多个文件。不要试图同时移动所有文件。它不需要移动到另一个文件,当然也不需要移动到一个文件中名称无关。只要在声明过程中使用不完整类型的代码遵循正式声明来完成类型,它就可以工作,即使在同一个源文件中。@WhozCraig我说过他可以包含包含整个网格定义的文件。我不知道你的意思是什么?@WhozCraig以及该文件是否名字是否相关并不取决于我自己。这只是一个例子。上面写的就是例子。
class Grid;
//
theGrid->Occupant(temp)