错误:尽管包含了头,但是类还没有被声明,并且其他地方的代码编译也很好

时间:2021-06-17 06:54:28

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:

因此,我有一个类包含在另一个类中,它不断抛出一个编译错误的表单“error: ' problems class '尚未声明”。文件是这样设置的:

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

任何形式的帮助都将得到极大的赞赏,无论多么含糊。我在win764位中使用了codeblocks 10.05和mingw4.4.1。

6 个解决方案

#1


71  

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。h来自使用problems class的文件。
  • 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.
  • 您可能在自己的头文件中或在使用它的地方拼写了problem类的名称。如果这是一个大小写错误,比如写problem类或problem类而不是problem类,就很难发现这一点。
  • 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.
  • 您可以将problem类放在名称空间a中,在这种情况下,如果是从名称空间a之外引用的话,您必须将problem类引用为:::problem类。
  • 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.
  • 您可能在include中拼错了文件名。如果您也有该文件的旧版本,且其名称拼写错误,编译器不会报告错误。
  • 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.
  • 您可以将问题类设置为只有在包含了问题类之后才能定义的宏。h,在这种情况下,你看到的问题类被宏预处理器取代了。
  • You could have defined ProblemClass in a header file other than problemclass.h and then problemclass.h actually defines something else.

  • 您可以在一个头文件中定义problems类,而不是problem类。h然后problemclass。h实际上定义了别的东西。
  • #2


    22  

    I've had that same error message as a result of a circular dependency in 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:

    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:

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

    #3


    2  

    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.

    请发布用于编译的命令。我已经看到了这个问题,如果您有两个单独的文件,其中包含相同的标题,并且您正在执行gcc *.cpp。这是因为#define是为整个gcc实例定义的,而不仅仅是为每个被编译的对象文件定义的。

    Ex.

    前女友。

    File1

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

    尝试同时编译所有文件将导致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,要么将每个文件编译成自己的对象文件,然后将它们链接到主应用程序中。

    #4


    1  

    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:

    我能想到的唯一一件事就是,如果在头文件之外重新定义了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 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.

    你可以尝试的一个想法是不要包含“problemclass”。aclass h’”。但是做一个问题类的前向声明。要实现这一点,您必须确保AClass的定义仅包含对problem类的引用或指针——您不希望编译器尝试使用需要其完整定义的problem类的大小。

    //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的编译单元。打开预处理的输出文件(通常是'。扩展)检查实际发生的事情。这是很方便的,尤其是当“包含”数量众多且难以预测的时候。

    #5


    1  

    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文件将跳过头文件中的定义。换句话说,第一行包含“problems class”。h”是跳过。

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

    在我的例子中,我在Linux下使用MingW64。假设我有一个头文件。

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

    In my main.cpp file:

    在我的主。cpp文件:

    // 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:

    cpp文件看起来是无辜的。然而,当unistd。包括h,它秘密地包括/usr/i686-w64-mingw32静态/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.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.

    现在您可以看到unistd的包含。h将导致包含io。从明月起,那将隐藏我的亲生骨肉。我想这和你的问题差不多。

    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的顺序(put #include 在IO.h后,程序编译。但这不是一个好的建议。我建议你不要用_IO_H_来保护你自己的IO.h。 )。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.

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

    #6


    1  

    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)

    Source(将抛出error SomeType_t未定义)

    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.

    这是一个愚蠢的,但很容易犯的错误,直到你把自己的头撞到桌子上造成了三次脑震荡后才发现。

    #1


    71  

    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。h来自使用problems class的文件。
  • 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.
  • 您可能在自己的头文件中或在使用它的地方拼写了problem类的名称。如果这是一个大小写错误,比如写problem类或problem类而不是problem类,就很难发现这一点。
  • 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.
  • 您可以将problem类放在名称空间a中,在这种情况下,如果是从名称空间a之外引用的话,您必须将problem类引用为:::problem类。
  • 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.
  • 您可能在include中拼错了文件名。如果您也有该文件的旧版本,且其名称拼写错误,编译器不会报告错误。
  • 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.
  • 您可以将问题类设置为只有在包含了问题类之后才能定义的宏。h,在这种情况下,你看到的问题类被宏预处理器取代了。
  • You could have defined ProblemClass in a header file other than problemclass.h and then problemclass.h actually defines something else.

  • 您可以在一个头文件中定义problems类,而不是problem类。h然后problemclass。h实际上定义了别的东西。
  • #2


    22  

    I've had that same error message as a result of a circular dependency in 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:

    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:

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

    #3


    2  

    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.

    请发布用于编译的命令。我已经看到了这个问题,如果您有两个单独的文件,其中包含相同的标题,并且您正在执行gcc *.cpp。这是因为#define是为整个gcc实例定义的,而不仅仅是为每个被编译的对象文件定义的。

    Ex.

    前女友。

    File1

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

    尝试同时编译所有文件将导致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,要么将每个文件编译成自己的对象文件,然后将它们链接到主应用程序中。

    #4


    1  

    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:

    我能想到的唯一一件事就是,如果在头文件之外重新定义了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 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.

    你可以尝试的一个想法是不要包含“problemclass”。aclass h’”。但是做一个问题类的前向声明。要实现这一点,您必须确保AClass的定义仅包含对problem类的引用或指针——您不希望编译器尝试使用需要其完整定义的problem类的大小。

    //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的编译单元。打开预处理的输出文件(通常是'。扩展)检查实际发生的事情。这是很方便的,尤其是当“包含”数量众多且难以预测的时候。

    #5


    1  

    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文件将跳过头文件中的定义。换句话说,第一行包含“problems class”。h”是跳过。

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

    在我的例子中,我在Linux下使用MingW64。假设我有一个头文件。

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

    In my main.cpp file:

    在我的主。cpp文件:

    // 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:

    cpp文件看起来是无辜的。然而,当unistd。包括h,它秘密地包括/usr/i686-w64-mingw32静态/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.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.

    现在您可以看到unistd的包含。h将导致包含io。从明月起,那将隐藏我的亲生骨肉。我想这和你的问题差不多。

    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的顺序(put #include 在IO.h后,程序编译。但这不是一个好的建议。我建议你不要用_IO_H_来保护你自己的IO.h。 )。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.

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

    #6


    1  

    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)

    Source(将抛出error SomeType_t未定义)

    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.

    这是一个愚蠢的,但很容易犯的错误,直到你把自己的头撞到桌子上造成了三次脑震荡后才发现。