C++ 编译错误枚举“没有命名类型”

Rém*_*VID 5 c++ enums types

以下代码:

foo.h

#include "bar.h"
class foo{ 
public:
   enum my_enum_type { ONE, TWO, THREE }; 
   foo(); 
   ~foo() {} 
};
Run Code Online (Sandbox Code Playgroud)

文件

foo::foo()
{
   int i = bar::MY_DEFINE;
}
Run Code Online (Sandbox Code Playgroud)

酒吧.h

#include "foo.h"
class bar{
public:
   static const int MY_DEFINE = 10;
   foo::my_enum_type var;
   bar() {};
   ~bar() {};
};
Run Code Online (Sandbox Code Playgroud)

使 g++ 编译器抱怨 my_enum_type “未命名类型”。为什么 ?所有标题都有多个包含定义(为清楚起见,此处未显示)。

谢谢

Bas*_*evs 5

问题:

  • 没有多重包含保护
  • 循环包含
  • 由循环包含引起的在声明之前使用类型

由 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() {} 
};
Run Code Online (Sandbox Code Playgroud)

这显然不是有效的 C++ 代码 - foo 在没有事先声明的情况下用于 bar body 中。与 Java 不同,C++ 要求在使用前声明类型。

  • 使用多重包含保护。根据您的平台,这些可能是#ifndef宏或#pragma once指令
  • 从 foo.h 中删除 bar.h 包含。
  • 在需要的地方放置前向声明(在您的情况下bar可能会在 foo.h 中进行前向声明,但您的示例并未显示这样做的必要性)。
  • 将尽可能多的实现移至 *.cpp 文件。

如果这些建议无法解决这种情况,请使用PIMPL idiom

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


Cas*_*Cow 5

您必须删除循环依赖,因此您需要为此目的将 foo.cpp 和 foo.h 视为不同的单位。

  • bar 类定义必须看到 foo::my_enum_type 所以可能 bar.h 包括 foo.h 是必要的。

  • foo 类定义不使用任何 bar,因此 foo.h 不需要包含 bar.h

  • foo.cpp 确实需要看到 MY_DEFINE 的 bar,所以 foo.cpp 应该包含 bar.h。这实际上也会自动引入 foo.h,但您可能希望无论如何都将它包含在 foo.cpp 中,以防您稍后删除依赖项。

大概你的标题有多个包含守卫。