char枚举中的值分配不正确

时间:2016-02-21 12:31:02

标签: c++ c++11 enums type-conversion implicit-conversion

我正在使用枚举,并尝试重现一些示例from this页面。最初的示例按预期工作,但我通过以下代码得到了一些有趣的结果:

#include <iostream>

enum num : char {
    zero = '0',
    one = '1',
    two = '2',
    three = '3',
    four = '4',
    five = '5',
    six = '6'
};

int main()
{
    const char two = '2';
    std::cout << two << std::endl;
    std::cout << num::two;
    return 0;
}

输出结果为:

  

2
  50

我预计两个结果都是一样的,但num::two似乎打印了一些其他值。此值也不会发生变化(50),因此我认为这不是随机/垃圾值&amp;有一些char / int解析正在完成,我不明白?这是the ideone link

我知道我可以通过像zero = 0这样分配来实现它,而不需要单引号就可以了。但是,我想知道幕后发生了什么,以及如何通过单引号分配控制可以打印的非单位数值。

4 个答案:

答案 0 :(得分:14)

根据C ++标准(4.5积分促销)

  

4未编码枚举类型的prvalue,其基础类型为   fixed(7.2)可以转换为其基础类型的prvalue。   此外,如果积分促销可以应用于其基础类型,   其基础类型固定的未作用域枚举类型的prvalue也可以转换为升级的基础的prvalue   型

因此,应用积分促销并且运算符&lt;&lt;对于int类型的对象被调用。

答案 1 :(得分:10)

当您说enum num : char时,您表示num内部以char实现,但仍然可以自动转换为整数值,即必然char

正如您引用的页面所说:

  

未范围的枚举类型的值可以隐式转换为   积分类型。

请参阅Why does a value of an enum with a fixed underlying type of char resolve to fct(int) instead of fct(char)?,了解有关C ++标准关于整体推广与固定基础类型组合的措辞中的问题的有趣讨论。

在任何情况下,您都可以将整个事情想象成具有私有char成员变量和公共int转换运算符的类:

// very similar to your enum:
class num {
private:
    char c;

public:
    num(char c) : c(c) {}
    operator int() const {
        return c;
    }
};

num two { '2' };
std::cout << two; // prints 50

要提高类型安全性并使std::cout行出现编译错误,只需将enum转换为enum class

enum class num : char

这与上面想象的class num类似,但没有转换运算符。

当您将num的实例提供给std::cout时,您就是num的客户端,并且逻辑上不认为输出格式将采用其内部{{1}考虑到实现。

要获得对输出格式的更多控制,您应该使用任何其他自定义类型,并为char重载operator<<。例如:

std::ostream

当然,枚举实例的特定#include <iostream> enum class num : char { zero = '0', one = '1', two = '2', three = '3', four = '4', five = '5', six = '6' }; std::ostream& operator<<(std::ostream& os, num const& n) { switch (n) { case num::zero: os << "Zero"; break; case num::one: os << "One"; break; case num::two: os << "Two"; break; case num::three: os << "Three"; break; // and so on } return os; } int main() { std::cout << num::two; // prints "Two" } 值现在变得毫无用处,所以你也可以完全摆脱它们:

char

这可能会让你觉得奇怪,但请记住,只有通用数字从0到6的枚举不是一个真实的用例。

答案 2 :(得分:7)

因为这两个调用两个不同的运算符重载:

  • 第一个调用operator<<std::ostream的非成员char。这会打印出角色。

  • 第二个示例由于整数提升而调用operator<<成员int,正如其他答案所解释的那样。

答案 3 :(得分:5)

原因是您的enum : charchar不同(这正是我们想要的 - 我们不希望枚举与其他类型相同,即使它们分配兼容 - 我们希望void func(num n)void func(char n)不同,对吗?)。

因此,由于enum num不是char,因此将使用operator<<(int),并打印整数值,即使基础类型为char。不完全合理,但我确定这就是发生的事情。