C++ VC++;2010年';缺少类型说明符';错误来来去去去而不改变代码

C++ VC++;2010年';缺少类型说明符';错误来来去去去而不改变代码,c++,visual-c++,include,visual-c++-2010,C++,Visual C++,Include,Visual C++ 2010,假设有四个文件:foo.h、foo.cpp、bar.h、bar.cpp foo.h: #pragma once class foo { // Whatever }; foo.cpp #include "foo.h" // Foo's definitions #include "foo.h" #include "bar.h" // Bar's definitions bar.h #pragma once class bar { bar(const foo &

假设有四个文件:foo.h、foo.cpp、bar.h、bar.cpp

foo.h:

#pragma once

class foo
{
    // Whatever
};
foo.cpp

#include "foo.h"

// Foo's definitions
#include "foo.h"
#include "bar.h"

// Bar's definitions
bar.h

#pragma once

class bar
{
    bar(const foo & f); // < C4430 'missing type specifier' (not always)
    // Other declarations
};
编译器说bar.h中有C4430。但奇怪的是,我能够通过注释然后取消注释这一行来构建代码。当然,构建失败,行也被注释,但当我取消注释它时,我得到了成功的构建。因此,相同的代码可能会也可能不会产生错误


我的VS是10.0.40219.1 SP1Rel,项目类型是Win32 DLL。

您需要在
bar.h
中包含
foo.h

#pragma once

#include "foo.h"
class bar
{
    bar(const foo & f);
};
如果需要完整的类定义,除非使用指针(在这种情况下,向前声明就足够了),否则需要包含声明类的文件

为什么有时编译,有时失败?

取决于编译器。我的猜测是
foo.h
包含在一个在到达
bar.h
之前编译的文件中。所以
bar.h
已经知道
foo
的定义。如果生成失败,将跳过成功编译的文件,并且可能不再包括
foo.h
。或者,如果仅在
x.cpp
中进行更改,编译器将只生成该文件,并可能跳过包含在已编译文件中的
foo.h

我希望我是清楚的

为什么你已经拥有的还不够?

你可以这么说

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

// Bar's definitions

包括
foo.h
bar.h
之前。确实如此,但是如果
bar.h
包含在
foo.h
之前的另一个位置,该怎么办?这就是为什么在bar.h中加入foo.h是个好主意。任何包含bar.h的文件都不再需要包含
foo.h
(编译时必须包含该文件),并且在文件中包含所需的所有内容更有意义。转发声明不是这种情况,但同样,您使用的是完整类型,而不是指针。

如果您只使用引用,而不是指针,那么声明也就足够了。