错误:尽管包含标头,但尚未声明类,并且代码在其他地方编译良好

发布于 2024-11-18 07:01:51 字数 666 浏览 2 评论 0原文

因此,我在另一个类中包含一个类,该类不断抛出“错误:'ProblemClass'尚未声明”形式的编译错误。文件是这样设置的:

#ifndef PROBLEMCLASS_H
#define PROBLEMCLASS_H

#include <iostream>
#include <cmath>

class ProblemClass
{
  public:

    virtual void Init() = 0;
};

#endif

发生错误的类如下所示:

#ifndef ACLASS_H
#define ACLASS_H

#include "problemclass.h"

class AClass : public Base
{
  public:

    void DoSomething(ProblemClass* problem);

};

#endif

编译错误发生在 void Dosomething();

我知道这里的代码不足以解决这个问题,所以我的问题更加笼统;有什么特别的原因吗?我应该寻找,或者我应该跟踪一些查询来追踪它?

代码都可以在几乎相同的项目版本中编译良好。

无论我使用的内容多么模糊,该 win 7 64 位中带有 mingw4.4.1 的代码块 10.05。

So I have a class included in another class that keeps throwing a compile error of the form "error: 'ProblemClass' has not been declared. The files are set up thusly:

#ifndef PROBLEMCLASS_H
#define PROBLEMCLASS_H

#include <iostream>
#include <cmath>

class ProblemClass
{
  public:

    virtual void Init() = 0;
};

#endif

and the class where the error occurs looks like this:

#ifndef ACLASS_H
#define ACLASS_H

#include "problemclass.h"

class AClass : public Base
{
  public:

    void DoSomething(ProblemClass* problem);

};

#endif

The compile error occurs at void Dosomething();

I'm aware the code here isn't enough to solve the problem. I've been unable to create a minimal example that can reproduce it. So my question is much more general; what sort of things might cause this? Is there anything in particular I should look for, or some line of enquiry I should be following to track it down?

This code compiles fine in an almost identical version of the project.

Help of any sort would be greatly appreciated, no matter how vague. I'm using codeblocks 10.05 with mingw4.4.1 in win 7 64 bit.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

天邊彩虹 2024-11-25 07:01:51

您似乎是在说您所显示的代码实际上并没有产生您遇到问题的编译器错误。所以我们只能猜测。以下是一些可能性:

  • 您可能忘记在使用 ProblemClass 的文件中包含 problemclass.h
  • 您可能在 ProblemClass 的头文件或使用它的地方拼写错误。如果是大小写错误,例如编写 ProblemclassproblemClass 而不是 ProblemClass,则可能很难发现。
  • 您可能已将包含防护 #defines 从一个头文件复制粘贴到另一个头文件,然后忘记更改定义的名称。那么只有这两个包含的头文件中的第一个才会生效。
  • 您可以将 ProblemClass 放置在命名空间 A 中,在这种情况下,您必须将 ProblemClass 引用为 A::ProblemClass > 如果您从命名空间 A 外部引用它。
  • 您可能正在使用模板,但并不期望两阶段查找能够以它的方式工作。
  • 您可能拼错了包含文件中的文件名。如果您在拼写错误的名称下还有该文件的旧版本,则编译器不会报告错误。
  • 您可以将 ProblemClass 设为一个只有在包含 problemclass.h 后才定义的宏,在这种情况下,您看到的 ProblemClass 会被替换为宏预处理器执行的其他操作。
  • 您可以在 problemclass.h 之外的头文件中定义 ProblemClass,然后 problemclass.h 实际上定义了其他内容。

You seem to be saying that the code you are showing doesn't actually produce the compiler error that you are having a problem with. So we can only guess. Here are some possibilities:

  • You could have forgot to include problemclass.h from the file where you are using ProblemClass.
  • You could have misspelled the name of ProblemClass either in its own header file or in the place where you are using it. This can be hard to spot if it is a capitalization error such as writing Problemclass or problemClass instead of ProblemClass.
  • You could have copy-pasted your inclusion guard #defines from one header file to another and then forgot to change the defined names. Then only the first of those two included header files would take effect.
  • You could have placed ProblemClass in a namespace A, in which case you must refer to ProblemClass as A::ProblemClass if you are referring to it from outside the namespace A.
  • You may be using templates and not expecting two-phase lookup to work the way it does.
  • You could have misspelled the file name in your include. The compiler would not report an error on that if you also have an old version of that file under the misspelled name.
  • You could have made ProblemClass a macro that only gets defined after you include problemclass.h, in which case what you see as ProblemClass gets replaced by something else by the macro preprocessor.
  • You could have defined ProblemClass in a header file other than problemclass.h and then problemclass.h actually defines something else.
拥醉 2024-11-25 07:01:51

由于头文件/类中的循环依赖,我收到了相同的错误消息:

foo.hpp:

#ifndef FOO_HPP
#define FOO_HPP

#include <stdio.h>
#include "bar.hpp" // <-- here

class Foo {
public:
    int value = 0;

    void do_foo(Bar myBar) {
        printf("foo + %d\n", myBar.value);
    }
};

#endif //FOO_HPP

bar.hpp:

#ifndef BAR_HPP
#define BAR_HPP

#include <stdio.h>
#include "foo.hpp" // <-- and here

class Bar {
public: 
    int value = 1;      

    void do_bar(Foo myFoo) {
        printf("bar = %d \n", myFoo.value);
    }
};

#endif //BAR_HPP

Compiling with: g++ -std=c++ 11 foo.hpp -o foo 产生以下输出:

In file included from foo.hpp:5:0:
bar.hpp:11:15: error: ‘Foo’ has not been declared
bar.hpp: In member function ‘void Bar::do_bar(int)’:
bar.hpp:12:32: error: request for member ‘value’ in ‘myFoo’, which is of non-class type ‘int’

I've had that same error message as a result of a circular dependency in my header files / classes:

foo.hpp:

#ifndef FOO_HPP
#define FOO_HPP

#include <stdio.h>
#include "bar.hpp" // <-- here

class Foo {
public:
    int value = 0;

    void do_foo(Bar myBar) {
        printf("foo + %d\n", myBar.value);
    }
};

#endif //FOO_HPP

bar.hpp:

#ifndef BAR_HPP
#define BAR_HPP

#include <stdio.h>
#include "foo.hpp" // <-- and here

class Bar {
public: 
    int value = 1;      

    void do_bar(Foo myFoo) {
        printf("bar = %d \n", myFoo.value);
    }
};

#endif //BAR_HPP

Compiling with: g++ -std=c++11 foo.hpp -o foo resulted in the following output:

In file included from foo.hpp:5:0:
bar.hpp:11:15: error: ‘Foo’ has not been declared
bar.hpp: In member function ‘void Bar::do_bar(int)’:
bar.hpp:12:32: error: request for member ‘value’ in ‘myFoo’, which is of non-class type ‘int’
最丧也最甜 2024-11-25 07:01:51

对于看到这篇文章并遇到此错误的任何人,我想指出,当我忘记在函数名称之前添加类说明符时,这种情况经常发生在我身上,其中该类函数使用类标头中私有定义的内容。

EG:

标题

class SomeClass
{
public:
    void SomeFunc();
private:
    typedef int SomeType_t;
};

源(将抛出错误 SomeType_t 未定义

void SomeFunc()
{
    SomeType_t dummy = 0;
}

源(已修复)

void SomeClass::SomeFunc()
{
    SomeType_t dummy = 0;
}

这是一个愚蠢但非常容易犯的错误,直到您因头部撞击而遭受三次脑震荡后才看到靠在桌子上。

To anyone seeing this post and having this error, I want to point out that this frequently happens to me when I forget to add the class specifier before a function name, wherein that class function uses something privately defined in the class's header.

EG:

Header

class SomeClass
{
public:
    void SomeFunc();
private:
    typedef int SomeType_t;
};

Source (Will throw error SomeType_t is not defined)

void SomeFunc()
{
    SomeType_t dummy = 0;
}

Source (Fixed)

void SomeClass::SomeFunc()
{
    SomeType_t dummy = 0;
}

This is a dumb, but really easy mistake to make and not see until after you have given yourself three concussions from hitting your head against the desk.

星軌x 2024-11-25 07:01:51

请发布您用于编译的命令。如果您有 2 个包含相同标头的单独文件并且您正在执行 gcc *.cpp,我就会看到此问题。发生这种情况是因为 #define 是为整个 gcc 实例定义的,而不仅仅是为正在编译的每个单独的目标文件定义的。

前任。

File1

#ifndef FILE1_HPP
#define FILE1_HPP 1
....
#endif

然后是引用它的两个单独的文件。

#include <file1.hpp>

尝试同时编译所有文件将导致其中一个 cpp 文件失败,因为 FILE1_HPP 已定义(导致该 cpp 文件的头文件被忽略)。

gcc -Wall *.cpp

答案是删除#ifndef,或者将每个文件编译成自己的目标文件,然后将它们链接到您的主应用程序中。

Please post the command you are using for compilation. I've seen this issue if you have 2 separate files that include the same header and you are doing a gcc *.cpp. This happens because the #define gets defined for the entire gcc instance and not just for each individual object file being compiled.

Ex.

File1

#ifndef FILE1_HPP
#define FILE1_HPP 1
....
#endif

Then two separate files that reference it.

#include <file1.hpp>

Trying to compile all at the same time will cause one of the cpp files to fail since FILE1_HPP was already defined (causing the header file to be ignored for that cpp file).

gcc -Wall *.cpp

Answer is either remove the #ifndef, or to compile each file into its own object files and then link them into your main application.

离去的眼神 2024-11-25 07:01:51

我遇到过类似的问题,我花了一段时间才找出原因。

根据您的情况,您可以在其他一些头文件中定义 PROBLEMCLASS_H。
结果是您的 cpp 文件将跳过头文件中的定义。换句话说,#include "problemclass.h" 行被跳过。

就我而言,我在 Linux 下使用 MingW64。假设我有一个头文件 IO.h:

// IO.h
#ifndef _IO_H_
#define _IO_H_

class A{
...
};
#endif

在我的 main.cpp 文件中:

// main.cpp
#include <unistd.h>
#include "IO.h"
int main(int argc, char** argv) {
 //...
}

cpp 文件看起来很无辜。但是,当包含 unistd.h 时,它会秘密包含 MingW 提供的 /usr/i686-w64-mingw32.static/include/io.h,并且此 >io.h 看起来像:

// io.h
#ifndef _IO_H_
#define _IO_H_
...
#endif /* End _IO_H_ */

现在您可以看到包含 unistd.h 将导致包含来自 MingW 的 io.h,并且这将隐藏我自己的 IO.h。我想这和你的问题类似。

如果您切换包含的顺序(将 #include 放在 IO.h 之后),程序将编译。但这不是一个好的建议。我建议您不要使用 _IO_H_ 来保护您自己的 IO.h。

要了解如何/为什么包含 PROBLEMCLASS_H ,我同意@greatwolf,您可以使用 g++ -E 输出预处理器输出并手动检查它。检查 PROBLEMCLASS_H 之前包含哪些文件以及它们包含的顺序。我希望这可以帮助解决您的问题。

I have experienced a similar problem and it took me a while to find out why.

In your case, you may define PROBLEMCLASS_H in some other header files.
The consequence is your cpp file will skip the definition in the header file. In other words, the line #include "problemclass.h" is skipped.

In my case, I am using MingW64 under Linux. Say I have a header file IO.h:

// IO.h
#ifndef _IO_H_
#define _IO_H_

class A{
...
};
#endif

In my main.cpp file:

// main.cpp
#include <unistd.h>
#include "IO.h"
int main(int argc, char** argv) {
 //...
}

The cpp file looks innocent. However, when unistd.h is included, it secretly includes /usr/i686-w64-mingw32.static/include/io.h supplied by MingW, and this io.h looks like:

// io.h
#ifndef _IO_H_
#define _IO_H_
...
#endif /* End _IO_H_ */

Now you can see that inclusion of unistd.h will lead to the inclusion io.h from MingW, and that will hide my own IO.h. I guess that's a similar problem like yours.

If you switch the order of includes (put #include <unistd.h> after IO.h), the program compiles. But this is not a good suggestion. I recommend that you don't use _IO_H_ to guard your own IO.h.

To understand how/why your PROBLEMCLASS_H is included, I agree with @greatwolf, you can use g++ -E to output the preprocessor output and manually examine it. Check what files are included before your PROBLEMCLASS_H and in what order they are included. I hope that can help solve your problem.

那请放手 2024-11-25 07:01:51

根据您所提供的内容,我能想到的唯一会导致编译错误的是,如果 PROBLEMCLASS_H 以某种方式在头文件之外重新定义。例如:

//main.cpp
#define PROBLEMCLASS_H
#include "aclass.h"

int main() {}

您可以尝试的一个想法是不在“aclass.h”中包含“problemclass.h”,而只是对 ProblemClass 进行前向声明。为此,您必须确保 AClass 的定义仅包含对 ProblemClass 的引用或指针——您不希望编译器尝试获取ProblemClass 需要其完整定义。

//aclass.h
#ifndef ACLASS_H
#define ACLASS_H

class ProblemClass;

class AClass : public Base
{
  public:
    void DoSomething(ProblemClass* problem);
};

#endif

您可以用来帮助追踪此标头问题的另一种技术是预处理有问题的“.cpp”编译单元。打开预处理的输出文件(通常是“.i”扩展名)并检查实际发生的情况。这非常方便,尤其是在“包含”数量众多且难以预测的情况下。

The only thing I could think of that would cause the compile error based on what you have presented is if PROBLEMCLASS_H somehow got redefined outside the header file. Like for example:

//main.cpp
#define PROBLEMCLASS_H
#include "aclass.h"

int main() {}

One idea you can try is to not include 'problemclass.h' in 'aclass.h' but just do a forward declare of ProblemClass instead. For this to work you have to make sure AClass's definition only contains references or pointers to ProblemClass -- you don't want the compiler to try and take the size of ProblemClass which would need its full definition.

//aclass.h
#ifndef ACLASS_H
#define ACLASS_H

class ProblemClass;

class AClass : public Base
{
  public:
    void DoSomething(ProblemClass* problem);
};

#endif

Another technique you can use to help track down this header problem is to just preprocess the problematic '.cpp' compilation unit. Open up the preprocessed output file(usually '.i' extension) and inspect what is actually happening. This is handy especially if the 'includes' are numerous and hard to predict.

赢得她心 2024-11-25 07:01:51

我遇到了同样的问题,并且发现了我做错了什么:按照您的示例,我将 ProblemClass 包含在 AClass 中,从而导致了问题。

I had the same problem and I've discovered what I was doing wrong: following your example, I've included ProblemClass in AClass, thus causing the problem.

倒数 2024-11-25 07:01:51

转发声明“ProblemClass”应该可以做到这一点。前向声明对于解决引发链接器/编译器错误的循环包含是必要的。
如果我遇到此类问题,请尽可能检查标题并进行前向声明,无论如何这是一个很好的做法。

Forward declare 'ProblemClass' should do the thing. Forward declarations are necessary to resolve circular includes that throw off linker/compiler errors.
If I have that kind of problems, a go through headers and make Forward Declaration whenever possible, which anyway is a good practice.

过度放纵 2024-11-25 07:01:51

遇到了同样的问题,
Ah 包含在 B1.h 和 B2.h 中
B2.h也包含在B2.cpp中

使用
#Pragma 一次
在课堂啊
这解决了问题。

Had the same problem,
A.h is included in B1.h and B2.h
B2.h is also included in B2.cpp

Used
#Pragma once
in class A.h
this resolved the issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文