C++ 错误:尽管包含头文件,但尚未声明类,并且代码在其他地方编译得很好

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6554492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:20:51  来源:igfitidea点击:

error: Class has not been declared despite header inclusion, and the code compiling fine elsewhere

c++compiler-errorsheader

提问by gj5

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();

编译错误发生在 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.

无论多么模糊,任何形式的帮助都将不胜感激。我在 win 7 64 位中使用代码块 10.05 和 mingw4.4.1。

回答by Bjarke H. Roune

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.
  • 您可能忘记在使用 ProblemClass 的文件中包含 problemclass.h。
  • 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.
  • 您可能在它自己的头文件中或在您使用它的地方拼错了 ProblemClass 的名称。如果是大写错误,例如编写 Problemclass 或 questionClass 而不是 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.
  • 您可能已经将包含保护 #defines 从一个头文件复制粘贴到另一个头文件,然后忘记更改定义的名称。然后只有这两个包含的头文件中的第一个才会生效。
  • 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.
  • 您可以将 ProblemClass 放在命名空间 A 中,在这种情况下,如果您从命名空间 A 外部引用它,则必须将 ProblemClass 引用为 A::ProblemClass。
  • 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.
  • 您可以将 ProblemClass 设为一个宏,该宏仅在您包含 problemclass.h 后才定义,在这种情况下,您看到的 ProblemClass 将被宏预处理器替换为其他内容。
  • You could have defined ProblemClass in a header file other than problemclass.h and then problemclass.h actually defines something else.

  • 您可以在除problemclass.h 之外的头文件中定义ProblemClass,然后problemclass.h 实际上定义了其他内容。

  • 回答by Manik

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

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

    foo.hpp:

    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:

    栏.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 fooresulted in the following output:

    编译: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'
    

    回答by Suroot

    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.

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

    Ex.

    前任。

    File1

    文件1

    #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).

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

    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.

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

    回答by greatwolf

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

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

    //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 ProblemClassinstead. 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 ProblemClasswhich would need its full definition.

    您可以尝试的一个想法是不要在 '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
    

    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.

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

    回答by zhanxw

    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.

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

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

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

    // IO.h
    #ifndef _IO_H_
    #define _IO_H_
    
    class A{
    ...
    };
    #endif
    

    In my main.cpp file:

    在我的 main.cpp 文件中:

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

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

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

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

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

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

    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.

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

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

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

    回答by L-S

    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)

    来源(会抛出错误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.

    这是一个愚蠢但非常容易犯的错误,直到你的头撞在桌子上给自己造成了三个脑震荡之后才能看到。

    回答by Raul Luna

    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.

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