C++编译错误 枚举“不是一种类型”的名称

5

The following code:

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++编译器抱怨我的枚举类型“未命名类型”。 为什么? 所有头文件都有多个包含定义(为了清晰起见未在此处显示)。
谢谢。

1
这应该可以正常工作... - Armen Tsirunyan
1
你如何使用这些类?这里还没有源文件。你能分享一下如何使用这些类吗? - Armen Tsirunyan
1
谢谢大家,你们让我意识到问题不在语法上,而是在我如何使用类上。在foo.h中有一个#include "bar.h",我用前向声明替换了它,现在一切都很好! - Rémy DAVID
2
@Rémy:所以,你展示的代码并不是你遇到问题的那段代码。道德教训:为了获得有用的答案,请展示真正的代码。 :-) 祝好! - Cheers and hth. - Alf
1
现在你遇到了循环包含的问题:foo.h 包含 bar.h,而 bar.h 又包含 foo.h。你不需要第一个文件。请给出一个能够重现你所看到的错误的小例子。 - vitaut
显示剩余3条评论
3个回答

6
问题:
  • 没有多重包含保护
  • 循环包含
  • 由循环包含引起类型在声明前使用

经过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++代码 - 在bar主体中使用了foo而没有先前的声明。与Java不同,C++要求在使用之前声明类型。
  • 使用多重包含保护。根据您的平台,这些可能是#ifndef宏或#pragma once指令
  • 从foo.h中删除bar.h的包含。
  • 在需要的地方放置前向声明(在您的情况下,bar可能在foo.h中进行前向声明,但您的示例并未揭示其必要性)。
  • 尽可能将实现移至*.cpp文件。

如果这些建议无法解决问题,请使用PIMPL惯用语

简而言之-只需从foo.h中删除#include"bar.h"指令即可。


我的头文件有多重包含保护。如果我从foo.h中删除bar.h,那么foo.cpp就不能再使用bar::MY_DEFINE了('bar'未被声明)。 - Rémy DAVID
错误。如果在foo.cpp中包含bar.h,那么foo.cpp仍然可以使用bar。 - Basilevs
是的,那就是我不知道的 ;) - Rémy DAVID

6

您必须消除循环依赖,因此需要将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中包含它,以防以后删除依赖项。

假设您的标题有多个包含保护。


1
我不知道你必须单独考虑 .h 和 .cpp 依赖关系。我认为在一个 .cpp 文件中包含多个 .h 是不好的设计。我可能错了,你的答案解决了我的问题。谢谢 :) - Rémy DAVID

2
foo()
{
   int i = bar::MY_DEFINE;
}

应该是

foo::foo()
{
   //...
}

请注意,此外还要注意到。
static const int MY_DEFINE = 10;

虽然它有一个初始化器,但仍然是一个声明。在bar.cpp中,您应该有以下行:

const int bar::MY_DEFINE;

同时,你不能在foo.h中包含bar.h,在bar.h中包含foo.h...这是不可能的 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接