我正在尝试做类似以下的事情:
enum E; void Foo(E e); enum E {A, B, C};
编译器拒绝的.我已经快速浏览了一下Google,而且共识似乎是"你做不到",但我无法理解为什么.谁能解释一下?
澄清2:我这样做是因为我在类中使用私有方法来获取枚举,并且我不希望枚举枚举值 - 例如,我不希望任何人知道E被定义为
enum E { FUNCTIONALITY_NORMAL, FUNCTIONALITY_RESTRICTED, FUNCTIONALITY_FOR_PROJECT_X }
因为项目X不是我希望用户了解的东西.
所以,我想转发声明枚举,以便我可以将私有方法放在头文件中,在cpp内部声明枚举,并将构建的库文件和标题分发给人.
至于编译器 - 它是GCC.
无法向前声明枚举的原因是,在不知道值的情况下,编译器无法知道枚举变量所需的存储.允许C++编译器根据包含指定的所有值所需的大小来指定实际存储空间.如果所有可见的是前向声明,则翻译单元无法知道将选择哪种存储大小 - 它可以是char或int,或其他.
从ISO C++标准的第7.2.5节:
枚举的基础类型是一个整数类型,可以表示枚举中定义的所有枚举器值.它是实现定义的,其中整数类型用作枚举的基础类型,除了基础类型不应大于
int
枚举器的值不能适合于int
或unsigned int
.如果枚举器列表为空,则基础类型就好像枚举具有值为0的单个枚举器.sizeof()
应用于枚举类型,枚举类型的对象或枚举器的值是sizeof()
应用于基础类型.
由于函数的调用者必须知道参数的大小才能正确设置调用堆栈,因此在函数原型之前必须知道枚举列表中的枚举数.
更新:在C++ 0X中,已经提出并接受了用于向前声明枚举类型的语法.您可以在http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf上查看该提案.
在C++ 0x中也可以进行枚举的前向声明.以前,枚举类型无法向前声明的原因是因为枚举的大小取决于其内容.只要枚举的大小由应用程序指定,就可以向前声明:
enum Enum1; //Illegal in C++ and C++0x; no size is explicitly specified. enum Enum2 : unsigned int; //Legal in C++0x. enum class Enum3; //Legal in C++0x, because enum class declarations have a default type of "int". enum class Enum4: unsigned int; //Legal C++0x. enum Enum2 : unsigned short; //Illegal in C++0x, because Enum2 was previously declared with a different type.
鉴于最近的发展,我在这里添加了一个最新的答案.
您可以在C++ 11中转发声明枚举,只要您同时声明其存储类型即可.语法如下所示:
enum E : short; void foo(E e); .... enum E : short { VALUE_1, VALUE_2, .... }
实际上,如果函数永远不会引用枚举的值,那么此时您根本不需要完整的声明.
G ++ 4.6及更高版本(-std=c++0x
或-std=c++11
更新版本)支持此功能.Visual C++ 2013支持这一点; 在早期版本中它有一些我尚未想到的非标准支持 - 我发现一些简单的前向声明是合法的,但是YMMV.
使用C++声明事物非常有用,因为它可以大大加快编译时间.你可以把用C宣布几件事情++包括:struct
,class
,function
,等...
但是你可以enum
在C++中转发声明吗?
不,你不能.
但为什么不允许呢?如果允许,您可以enum
在头文件中定义类型,并enum
在源文件中定义值.听起来应该被允许对吗?
错误.
在C++中,没有enum
类似C#(int)中的默认类型.在C++中,您的enum
类型将由编译器确定为适合您的值范围的任何类型enum
.
那是什么意思?
这意味着enum
在获得已enum
定义的所有值之前,无法完全确定您的基础类型.哪个男人你不能分开你的声明和定义enum
.因此,您无法enum
在C++中转发声明.
ISO C++标准S7.2.5:
枚举的基础类型是一个整数类型,可以表示枚举中定义的所有枚举器值.它是实现定义的,其中整数类型用作枚举的基础类型,除了基础类型不应大于
int
枚举器的值不能适合于int
或unsigned int
.如果枚举器列表为空,则基础类型就好像枚举具有值为0的单个枚举器.sizeof()
应用于枚举类型,枚举类型的对象或枚举器的值是sizeof()
应用于基础类型.
您可以使用sizeof
运算符确定C++中枚举类型的大小.枚举类型的大小是其基础类型的大小.通过这种方式,您可以猜出编译器正在使用哪种类型enum
.
如果您明确指定明确的类型,该怎么办enum
:
enum Color : char { Red=0, Green=1, Blue=2}; assert(sizeof Color == 1);
你能转发申报enum
吗?
不,但为什么不呢?
指定a的类型enum
实际上不是当前C++标准的一部分.它是VC++扩展.它将成为C++ 0x的一部分.
资源
[我的回答是错的,但我把它留在这里,因为评论很有用].
前向声明枚举是非标准的,因为指向不同枚举类型的指针不能保证大小相同.编译器可能需要查看定义以了解可以使用此类型的大小指针.
实际上,至少在所有流行的编译器上,指向枚举的指针是一致的大小.例如,通过Visual C++提供枚举的前向声明作为语言扩展.
确实没有枚举的前瞻性声明.由于枚举的定义不包含任何可能依赖于使用枚举的其他代码的代码,因此在首次声明时完全定义枚举通常不是问题.
如果枚举的唯一用途是私有成员函数,则可以通过将枚举本身作为该类的私有成员来实现封装.枚举仍然必须在声明点完全定义,即在类定义中.然而,这不是一个更大的问题,因为在那里声明私有成员函数,并不是更糟糕的实现内部的暴露.
如果您需要对实现细节进行更深入的隐藏,可以将其分解为抽象接口,仅包含纯虚函数,以及实现(继承)接口的具体,完全隐藏的类.类实例的创建可以由工厂或接口的静态成员函数处理.这样,即使是真正的类名,更不用说它的私有函数了,也不会暴露出来.
只是指出原因实际上是在向前声明后还不知道枚举的大小。好吧,您可以使用结构的前向声明来传递指针或从前向声明的结构定义本身所引用的位置引用对象。
向前声明枚举不会太有用,因为人们希望能够传递枚举值。您甚至都没有指向它的指针,因为最近我被告知某些平台对char使用与int或long不同的大小的指针。因此,这完全取决于枚举的内容。
当前的C ++标准明确禁止做类似的事情
enum X;
(在中7.1.5.3/1
)。但接下来的C ++标准,由于明年允许以下,这使我确信实际问题具有与基本型的事:
enum X : int;
它被称为“不透明”枚举声明。您甚至可以在以下代码中按值使用X。并且其枚举数可以稍后在枚举的重新声明中进行定义。请参阅7.2
当前工作草案。