如何在C++的switch语句中使用全名提升代码可读性?
问题描述
我是C新手,目前正在阅读Bjarne Stroustrup的《C编程原理与实践》。作为练习,我正在为终端计算器编写词法分析器和语法分析器,该分析器会判断表达式字符串中单个字符的类型,并为令牌分配对应的类型值。
以下是判断令牌类型的函数片段(为简化代码,未包含完整函数及所有分支):
switch(c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': return 'n'; // 'n' for number case '*': case '/': return 'm'; // m for multiplication or division case '(': case ')': return 'p'; // p for parenthesis case ' ': // whitespace return 'w'; default: throw std::invalid_argument("Invalid token: A non-valid character was passed to determineKind"); }
我使用字符表示令牌类型,是因为后续可以使用简洁的switch语句,而非可读性较差的、用字符串表示类型的if语句。但同时,'n'、'm'、'p'、'w'属于魔法常量,这又降低了解析器代码的可读性。
请问是否有办法在switch语句中使用“number”“whitespace”“parenthesis”这类全名,让代码更简洁易懂?
解决方案
用C++的**枚举类型(enum class)**就能完美解决这个问题——既保留switch语句的简洁性,又能用语义化全名替代魔法常量,大幅提升代码可读性。
1. 定义语义化枚举类
先定义一个enum class(推荐使用,避免命名污染和隐式类型转换问题),为每种令牌类型赋予清晰的名称:
#include <stdexcept> enum class TokenKind { Number, // 数字 MulDiv, // 乘除运算符 Parenthesis, // 括号 Whitespace // 空白符 };
2. 修改令牌类型判断函数
将原函数的返回类型改为TokenKind,直接返回枚举值替代魔法字符:
TokenKind determineKind(char c) { switch(c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': return TokenKind::Number; case '*': case '/': return TokenKind::MulDiv; case '(': case ')': return TokenKind::Parenthesis; case ' ': return TokenKind::Whitespace; default: throw std::invalid_argument("Invalid token: A non-valid character was passed to determineKind"); } }
3. 后续switch语句示例
在语法分析器中使用令牌类型时,switch逻辑会非常直观,无需额外注释就能理解:
void processToken(TokenKind kind) { switch(kind) { case TokenKind::Number: // 处理数字逻辑 break; case TokenKind::MulDiv: // 处理乘除运算逻辑 break; case TokenKind::Parenthesis: // 处理括号逻辑 break; case TokenKind::Whitespace: // 处理空白符逻辑 break; // 按需添加其他分支 } }
为什么选enum class?
- 强类型安全:枚举值不会隐式转换为整数,避免意外类型错误;
- 无命名冲突:必须通过
TokenKind::前缀访问枚举值,不用担心和其他代码的同名变量冲突; - 可读性强:语义化名称让代码自解释,无需依赖注释辅助理解。
若需兼容C++11之前的版本,也可以使用普通enum,但要注意避免命名空间冲突问题。
内容的提问来源于stack exchange,提问作者a_floating_point
相关产品推荐
相关产品推荐

