TL;DR: C++ 的设计者不喜欢类型双关语。
其他人指出了为什么标准不允许这样做;我将尝试解释为什么标准的作者可能会这样做。根据这个提议,强类型枚举的主要动机是类型安全。不幸的是,类型安全对很多人来说意味着很多事情。假设一致性是标准委员会的另一个目标是公平的,所以让我们在 C++ 的其他相关上下文中检查类型安全。
C++ 类型安全
通常在 C++ 中,类型是不相关的,除非明确指定为相关(通过继承)。考虑这个例子:
class A
{
double x;
int y;
};
class B
{
double x;
int y;
};
void foo(A* a)
{
B* b = static_cast<B*>(a); //error
}
即使 A 和 B 具有完全相同的表示形式(标准甚至称它们为“标准布局类型”),如果没有reinterpret_cast
. 同样,这也是一个错误:
class C
{
public:
int x;
};
void foo(C* c)
{
int* intPtr = static_cast<int*>(c); //error
}
即使我们知道 C 中唯一的东西是 int 并且您可以自由访问它,但还是static_cast
失败了。为什么?没有明确指定这些类型是相关的。C++ 旨在支持面向对象的编程,它提供了组合和继承之间的区别。您可以在通过继承相关的类型之间进行转换,但不能在通过组合相关的类型之间进行转换。
根据您所看到的行为,很明显强类型枚举通过组合与其基础类型相关联。为什么这可能是标准委员会选择的模型?
组合与继承
有很多关于这个问题的文章比我在这里能写的更好,但我会尝试总结一下。何时使用组合与何时使用继承当然是一个灰色地带,但在这种情况下有很多点支持组合。
- 强类型枚举不打算用作整数值。因此,由继承指示的“is-a”关系不适合。
- 在最高级别上,枚举旨在表示一组离散值。这是通过为每个值分配一个 id 号来实现的这一事实通常并不重要(不幸的是,C 公开并因此强制执行这种关系)。
- 回顾一下提案,列出的允许指定底层类型的原因是指定枚举的大小和签名。这更像是一个实现细节,而不是枚举的重要部分,再次有利于组合。
在这种情况下,您可能会争论好几天是继承还是组合更好,但最终必须做出决定,并且行为是以组合为模型的。