C++从字符类型创建枚举类型

6
好的,我是一个C++的新手。我买了Bjarne的书,正在尝试跟着计算器代码走。
然而,编译器在这段代码上报错:
token_value get_token()
{
    char ch;

    do {        // skip whitespace except '\n'
        if(!std::cin.get(ch)) return curr_tok = END;
    } while (ch!='\n' && isspace(ch));

    switch (ch) {
        case ';':
        case '\n':
            std::cin >> WS;      // skip whitespace
            return curr_tok=PRINT;
        case '*':
        case '/':
        case '+':
        case '-':
        case '(':
        case ')':
        case '=':
            return curr_tok=ch;
        case '0': case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9': case '.':
            std::cin.putback(ch);
            std::cin >> number_value;
            return curr_tok=NUMBER;
        default:            // NAME, NAME=, or error
            if (isalpha(ch)) {
                char* p = name_string;
                *p++ = ch;
                while (std::cin.get(ch) && isalnum(ch)) *p++ = ch;
                std::cin.putback(ch);
                *p = 0;
                return curr_tok=NAME;
            }
            error("bad token");
            return curr_tok=PRINT;
}

它输出的错误信息是这样的:
calc.cpp:42: error: invalid conversion from ‘char’ to ‘token_value’

token_value 是一个看起来像这样的枚举类型:

enum token_value {
    NAME,       NUMBER,     END,
    PLUS='+',   MINUS='-',  MUL='*',  DIV='/',
    PRINT=';',  ASSIGN='=', LP='(',   RP=')'
};
token_value curr_tok;

我的问题是,我如何将来自cin的ch转换为关联的枚举值?
5个回答

11

你不能将char隐式地转换为enum - 你必须显式地进行转换:

return curr_tok = static_cast<token_value> (ch);

但要小心!如果你的enum值都与你的char不匹配,那么使用结果将会很困难 :)


4
请注意,所提供的解决方案(即告诉您使用static_cast)之所以能正确工作,仅仅是因为在定义枚举符号时,符号(例如PLUS)被定义为具有与底层字符值相等的物理/数字值(例如'+')。

另一种方法(不使用转换)是使用switch/case语句明确指定每个字符值返回的枚举值,例如:

    case '*':
      return curr_tok=MUL;
    case '/':
      return curr_tok=DIV;

1

你需要进行显式转换:

curr_tok = static_cast<token_value>(ch);

原因是将整数类型转换为枚举类型是危险的。如果该值对于枚举类型无效,则行为是未定义的。因此,语言不允许您通过隐式转换意外地执行此操作。显式转换应该意味着“我知道自己在做什么,并且已经检查了该值是否有效”。

0

我认为我不会尝试显式设置枚举符号的值,而是为您在switch语句中的每个符号编写一个case。如果出现问题,以这种方式进行调试可能会更加困难,而编写每个符号的情况的性能成本非常低,甚至不值得考虑(除非您正在为某种极低端嵌入式系统编写代码,但即使如此也不值得)。


-1
return curr_tok=(token_value)ch;

2
在使用C++时,最好使用新式转换(即static_cast等),而不是C风格的转换。 - ChrisW
或者,如果您确实想使用C风格的转换,可以使用构造函数语法来隐藏它们:curr_tok = token_value(ch)。即使只能使用C风格的转换来调用单参数构造函数,但您的样式指南作者在禁止它们之前可能会三思而后行。;-) - Steve Jessop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接