以下代码:
foo.h中
#include "bar.h"
class foo{
public:
enum my_enum_type { ONE, TWO, THREE };
foo();
~foo() {}
};
Foo.cpp中
foo::foo()
{
int i = bar::MY_DEFINE;
}
bar.h
#include "foo.h"
class bar{
public:
static const int MY_DEFINE = 10;
foo::my_enum_type var;
bar() {};
~bar() {};
};
让g ++编译器抱怨my_enum_type“没有命名类型”。 为什么? 所有标题都有多个包含定义(为清楚起见,此处未显示)。
由于
答案 0 :(得分:4)
问题:
由C预处理器处理的foo.h看起来像无限空字符串序列。
通过多重包含保护,foo.h被预处理为:
> cpp foo.h
class bar{ // preprocessed from #include "bar.h"
public:
static const int MY_DEFINE = 10;
foo::my_enum_type var;
bar() {};
~bar() {};
};
// end of #include "bar.h"
class foo{
public:
enum my_enum_type { ONE, TWO, THREE };
foo();
~foo() {}
};
这显然不是一个有效的C ++代码 - foo用在bar体中而没有事先声明。与Java不同,C ++需要在使用之前声明类型。
#ifndef
宏或#pragma once
指令bar
可能在foo.h中向前声明,但您的示例并未透露此内容的必要性。)如果无法使用这些建议解决问题,请使用PIMPL idiom。
简而言之 - 只需从foo.h中删除#include "bar.h"
指令
答案 1 :(得分:2)
foo()
{
int i = bar::MY_DEFINE;
}
应该是
foo::foo()
{
//...
}
另请注意
static const int MY_DEFINE = 10;
仍然是一个声明,虽然它有一个初始化器。在bar.cpp中,您应该有以下行
const int bar::MY_DEFINE;
此外,您不能在f.h中包含bar.h,也不能在bar.h中包含foo.h ......这在物理上是不可能的:)
答案 2 :(得分:2)
您必须删除循环依赖项,因此您需要将foo.cpp和foo.h视为不同的单位。
bar类定义必须看到foo :: my_enum_type所以可能bar.h包括foo.h是必需的。
foo类定义不使用任何bar,因此foo.h不需要包含bar.h
foo.cpp确实需要查看MY_DEFINE的栏,所以foo.cpp应该包含bar.h.这实际上也会自动引入foo.h,但你可能希望在foo.cpp中包含它,以防你以后删除依赖。
据推测,你的标题有多个包含警戒。