我只是好奇枚举类是否可以是最终的......因为编译器给了我矛盾的结果。
考虑代码:
#include <iostream>
enum class some_enums final : char
{
a = 'a',
b = 'b',
c = 'c'
};
int main()
{
some_enums aa = some_enums::a;
std::cout << "aa=" << static_cast<char>(aa) << std::endl;
}
使用 Visual Studio 2015 编译器(http://rextester.com/l/cpp_online_compiler_visual)编译它可以工作......但是使用 clang 编译它(http://rextester.com/l/cpp_online_compiler_clang)给了我一个错误:
source_file.cpp:3:30: error: expected ';' after top level declarator
enum class some_enums final : char
我在标准中的任何地方都没有看到最终枚举类的痕迹,因此我将功劳归于 clang ...但是,为什么 Visual Studio 在这种情况下接受它,尽管 MSDN 中没有提及(https://msdn.microsoft.com)。 com/en-us/library/2dzy4k6e.aspx)?
final
说明符用于表示不能继承某个类。由于 enum class
无法继承,因此您的情况中使用的 final
说明符是无用的。
来自 here 的“Stollen”,也在 §7.2/p1 枚举声明 [dcl.enum] 中提及 ,
class enum
声明的形式为:
enum-key attr(optional) nested-name-specifier(optional) identifier enum-base(optional) ;
enum-key
- enum
、enum class
(自 C++11 起)或 enum struct
(自 C++11 起)attr
(C++11) - 任意数量属性的可选序列identifier
- 正在声明的枚举的名称。如果存在,并且如果此声明是重新声明,则其前面可能带有 nested-name-specifier
(C++11 起):名称和作用域解析运算符 ::
的序列,以作用域解析运算符结尾。仅在无作用域枚举声明中可以省略该名称。enum-base
(C++11) - 冒号 (:),后跟命名整型的 type-specifier-seq
(如果是 cv-qualified
,则忽略限定条件)。enumerator-list
- 以逗号分隔的枚举器定义列表,每个定义要么只是一个标识符(成为枚举器的名称),要么是带有初始值设定项的标识符:identifier = constexpr
。在任何一种情况下,标识符后面都可以直接跟有可选的属性说明符序列。 (自 C++17 起)。因此,使用
enum class
说明符定义 final
为:
enum class some_enums final : char {
...
};
不是标准形式。
这与“枚举类可以是最终的吗?”问题没有直接关系,而是对该主题的类似或后续问题的回答;枚举可以标记为“最终” - 又名“将来不会改变”。
如果您使用与 Swift 等语言互操作的语言,编译器会告诉您处理未知情况。
enum class MyEnum {
first,
second
};
在斯威夫特:
let myEnum: MyEnum = .first
switch myEnum {
case .first: return 1
case .second: return 2
}
Swift 编译器会抱怨:
Switch covers known cases, but 'MyEnum' may have additional unknown values
。
您需要向开关添加一个 @unknown default: ...
分支,如果您自己创建 MyEnum
枚举,则有点不必要。
在这种情况下,您可以使用 clang 扩展
enum_extensibility
:
enum class MyEnum {
first,
second
} __attribute__((enum_extensibility(closed)));
..Swift 将不再抱怨缺少
@unknown default
分支! :)