C++11 中的最终枚举类

问题描述 投票:0回答:2

我只是好奇枚举类是否可以是最终的......因为编译器给了我矛盾的结果。

考虑代码:

#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)?

c++ c++11 enums final
2个回答
8
投票

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 {
...
};

不是标准形式。


0
投票

这与“枚举类可以是最终的吗?”问题没有直接关系,而是对该主题的类似或后续问题的回答;枚举可以标记为“最终” - 又名“将来不会改变”。

如果您使用与 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
分支! :)

© www.soinside.com 2019 - 2024. All rights reserved.