我想做的事情如下:

enum E;

void Foo(E e);

enum E {A, B, C};

编译器拒绝它。我在谷歌上快速浏览了一下,共识似乎是“你做不到”,但我不明白为什么。有人能解释一下吗?

澄清2:我这样做是因为我在一个类中有私有方法,它采用所说的枚举,我不希望枚举的值暴露出来-因此,例如,我不希望任何人知道E被定义为

enum E {
    FUNCTIONALITY_NORMAL, FUNCTIONALITY_RESTRICTED, FUNCTIONALITY_FOR_PROJECT_X
}

项目X不是我想让我的用户知道的东西。

所以,我想要转发声明枚举,这样我就可以把私有方法放在头文件中,在cpp中内部声明枚举,并将构建的库文件和头分发给人们。

至于编译器——它是GCC。


当前回答

对于iOS/Mac/Xcode上面临这种情况的人,

如果你在XCode中用Objective-C集成C/ c++头文件时遇到这个问题,只需将文件扩展名从。mm更改为。m即可

其他回答

[我的答案是错误的,但我把它留在这里,因为评论很有用]。

前向声明枚举是非标准的,因为指向不同枚举类型的指针不能保证大小相同。编译器可能需要查看定义才能知道该类型可以使用哪些大小指针。

实际上,至少在所有流行的编译器上,指向枚举的指针的大小是一致的。例如,枚举的前向声明是由Visual c++作为语言扩展提供的。

我只是注意到,原因实际上是,在向前声明后,enum的大小还不知道。你使用一个结构的前向声明来传递一个指针,或者从一个在前向声明的结构定义本身中引用的地方引用一个对象。

向前声明枚举不是很有用,因为人们希望能够按值传递枚举。你甚至不能有指向它的指针,因为我最近被告知一些平台使用不同大小的指针用于char和int或long。所以这一切都取决于枚举的内容。

当前的c++标准明确禁止这样做

enum X;

(在7.1.5.3/1)。但下一个c++标准将于明年发布,允许以下功能,这让我确信问题实际上与底层类型有关:

enum X : int;

它被称为“不透明”枚举声明。您甚至可以在以下代码中按值使用X。并且它的枚举数可以稍后在枚举的重新声明中定义。参见当前工作草案中的7.2。

对于iOS/Mac/Xcode上面临这种情况的人,

如果你在XCode中用Objective-C集成C/ c++头文件时遇到这个问题,只需将文件扩展名从。mm更改为。m即可

事实上,没有所谓的提前宣布全体会议。由于枚举的定义不包含任何可能依赖于使用该枚举的其他代码的代码,因此在第一次声明枚举时完全定义它通常不是问题。

如果枚举的唯一用途是私有成员函数,则可以通过将枚举本身作为该类的私有成员来实现封装。枚举仍然必须在声明时完全定义,即在类定义中。然而,与在那里声明私有成员函数相比,这并不是一个更大的问题,也没有比这更糟糕的实现内部公开了。

如果您需要对实现细节进行更深层次的隐藏,您可以将其分解为一个抽象接口(仅由纯虚函数组成)和一个具体的、完全隐藏的实现(继承)接口的类。类实例的创建可以由工厂或接口的静态成员函数处理。这样,即使是真正的类名也不会被暴露,更不用说它的私有函数了。

enum不能被前向声明的原因是,如果不知道值,编译器就不能知道enum变量所需的存储空间。c++编译器可以根据包含所有指定值所需的大小指定实际存储空间。如果所有可见的都是前向声明,那么翻译单元就不能知道所选择的存储大小是什么——它可能是char型、int型或其他类型。


ISO c++标准第7.2.5节:

The underlying type of an enumeration is an integral type that can represent all the enumerator values defined in the enumeration. It is implementation-defined which integral type is used as the underlying type for an enumeration except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int. If the enumerator-list is empty, the underlying type is as if the enumeration had a single enumerator with value 0. The value of sizeof() applied to an enumeration type, an object of enumeration type, or an enumerator, is the value of sizeof() applied to the underlying type.

由于函数的调用者必须知道参数的大小才能正确地设置调用堆栈,因此枚举列表中的枚举数必须在函数原型之前知道。

更新:

在c++ 0X中,已经提出并接受了向前声明enum类型的语法。你可参阅前向申报枚举数(修订版3)的建议