开发者

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

开发者 https://www.devze.com 2023-03-16 16:55 出处:网络
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:

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 identi开发者_运维百科cal 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.


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.


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’


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.


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.


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.


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.


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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消