C++错误:" 'class' does not name a type"和"invalid use of incomplete type ‘struct ...' "



这是一个非常重复的问题,在StackOverflow中也是如此,但是即使尝试不同的答案,我也无法解决我的问题。所以,我有一些课程:

主.cpp:

#include "foo.h"
#include "bar.h"
...

傅炯:

#include "bar.h"
class foo {
foo();
bar& bind(bar &b);
gru& bind(gru &g);
};

酒吧:

#include "foo.h"
class bar {
bar();
foo& bind(foo &f);
gru& bind(gru &g);
};

显然,我有一种循环依赖。所以我得到了臭名昭著的错误'bar' does not name a type.在这种情况下,我将class bar;添加到foo声明并删除#include。当我这样做时,我得到:invalid use of incomplete type ‘struct bar'

我尝试了一些不同的方式,也向栏添加了class foo;,但我总是有某种错误。在最后一种情况下,我得到:

bar.cpp:48:11: error: prototype for ‘foo& bar::bind(bar::foo&)’ does not match any in class ‘bar’
bar.h:55:12: error: candidates are: gru& bar::bind(gru&)
bar.h:54:13: error:                 bar::foo& bar::bind(bar::foo&)

另外,我从来没有收到过任何关于gru的抱怨。作为附加信息,该程序中已经存在,在我添加foo之前,该程序已经与barmain完美配合

。有什么有用的想法吗?非常感谢:)

in foo.h

#pragma once //(or use a guard symbol)
class bar;
class foo
{
bar & bind(bar & b);
};

在巴尔·

#pragma once //(or use a guard symbol)
class foo;
class bar
{
foo & bind(foo & f);
};

在福.cpp

#include <foo.h>
#include <bar.h>
bar foo:bind(bar & b)
{
// here you can use bar methods
}

在酒吧.cpp

#include <bar.h>
#include <foo.h>
foo bar:bind(foo & f)
{
// here you can use foo methods
}

这对我来说编译得很好(注意:这没有实例化 foo 或 bar 类):

文件栏.h 包含:

#ifndef BAR_H
#define BAR_H
#include "foo.h"
class foo;
class gru;
class bar {
bar();
foo& bind(foo &f);
gru& bind(gru &g);
};
#endif

文件 foo.h 包含:

#ifndef FOO_H
#define FOO_H
#include "bar.h"
class bar;
class gru;
class foo {
foo();
bar& bind(bar &b);
gru& bind(gru &g);
};
#endif

主.cpp文件包含:

#include "foo.h"
#include "bar.h"

非常感谢你们的回答。在许多方面,他们很有帮助。

最后,我意识到我必须重新排序代码中的所有#include,因为,正如您可能已经意识到的那样,有更多的编码,我放在这里是一个更简单的版本(抱歉)。

因此,我的最终解决方案是将class bar;包含在foo.h中,class foo;包含在bar.h中。然后对main.cpp和生成文件中的包含重新排序。

再次感谢;-)

C++编译器非常古老,此外,在代码中处理此示例的部分不是编译器本身,而是编译器链的一部分,称为预处理器。如果我们同意C++编译器不是很聪明,那么预处理器是一个沉闷但友好的助手。

编译 *.cpp 文件,稍后与程序中的其他 *.cpp 文件链接。.h文件本身实际上没有任何意义:这种分离对程序员来说应该是一个优势。这里的关键点是,无论您在 *.cpp 文件中包含多少 *.h 文件,最终都会有一个巨大的、生成的 cpp 文件,其中包含 *.h 文件中存在的整个代码,以及 *.cpp 文件中存在的源代码。

循环依赖可以通过多种方式解决,但是,正如您可以想象的那样,编译器在问题产生之前甚至没有机会处理任何事情。C 或 C++ 不支持循环依赖关系。

更现代的编译器(如JavaC#)能够提取类的公共接口,并在B类需要A类时使用此信息,反之亦然。同样,这在C++是不可能的。

唯一的解决方案是重写代码。目标是消除循环#include指令。实际上,如果您的代码像您在此处显示的那样简单,则可以使用前向声明轻松解决它:

// foo.h
class bar;
class foo {
foo();
bar& bind(bar &b);
gru& bind(gru &g);
};

--

// bar.h
class foo;
class bar {
bar();
foo& bind(foo &f);
gru& bind(gru &g);
};

--

// main.cpp
#include "foo.h"
#include "bar.h"
// ...
int main()
{
// ...
}

前向声明可以让编译器知道这个类实际上将要存在,并且你提前声明它的存在,但没有提供有关其内容的详细信息。这就是为什么你可以把这个前向声明用于另一个类中的指针(或引用)(编译器需要转发类的大小才能创建属性,如果没有细节,这是不可能的)。

这里还有其他概念需要处理,例如编译器保护。

希望这有帮助。

相关内容

  • 没有找到相关文章

最新更新