Yegor
Yegor

Reputation: 2606

VC++ 2010: 'missing type specifier' errors come and go without changes to code

Let's assume there are four files: foo.h, foo.cpp, bar.h, bar.cpp.

foo.h:

#pragma once

class foo
{
    // Whatever
};

foo.cpp

#include "foo.h"

// Foo's definitions

bar.h

#pragma once

class bar
{
    bar(const foo & f); // < C4430 'missing type specifier' (not always)
    // Other declarations
};

bar.cpp

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

// Bar's definitions

The compiler says there is C4430 in bar.h. But the strange thing is that I'm able to build the code by commenting and then uncommenting back that line. Of course, build fails with the line being commented as well, but when I uncomment it I get successful build. So the same code may or may not produce errors.

My VS is 10.0.40219.1 SP1Rel and the project type is Win32 DLL.

Upvotes: 1

Views: 186

Answers (1)

Luchian Grigore
Luchian Grigore

Reputation: 258618

You need to include foo.h in bar.h:

#pragma once

#include "foo.h"
class bar
{
    bar(const foo & f);
};

If you need a full class definition, which you do unless you're using a pointer (in which case a forward declaration would suffice), you need to include the file where the class is declared.

Why does it compile sometimes and sometimes it fails?

Depends on the compiler. My guess is foo.h is included in a file that gets compiled before bar.h is reached. So bar.h already knows about foo's definition. If the build fails, the files that were succesfully compiled are skipped, and possibly foo.h no longer included. Or if you make a change only in x.cpp, the compiler will only build that file and possibly skip the inclusion of foo.h, which was included in a file that is already compiled.

I hope I was clear.

Why what you already have isn't enough?

You might say that

//Bar.cpp
#include "foo.h"
#include "bar.h"

// Bar's definitions

includes foo.h before bar.h. Indeed, but what if bar.h is included before foo.h in a different place? That's why it is a good idea to include foo.h in bar.h. Any file including bar.h will no longer need to include foo.h (which it must in order to compile), and it makes more sense to include everything you need in the file. This isn't the case with forward declarations, but, again, you're using a complete type, not a pointer.

Upvotes: 2

Related Questions