为什么开关大小写语句中不能有变量?
Why can't I have a variable in switch-case statement?
这是我的代码:
bool Character::keyPress(char c)
{
switch(c)
{
case up_key:
move(0, -1);
break;
case down_key:
move(0, 1);
break;
case left_key:
move(-1, 0);
break;
case right_key:
move(1,0);
break;
default:
return false;
}
return true;
}
编译器抱怨道:
error C2051: case expression not constant
error C2051: case expression not constant
error C2051: case expression not constant
error C2051: case expression not constant
在我的头文件中,我有:
protected:
char up_key;
char down_key;
char right_key;
char left_key;
我使用的是Visual C++2008。
正如错误消息所述,大小写表达式必须是常量。编译器在编译时将其构建为一个非常快速的查找表,如果值可能随着程序的运行而更改,则无法做到这一点。
如果您确实需要它们是可变的,而不是恒定的,那么最好使用If/else语句。
替换这个冗长笨拙的代码,
switch(c)
{
case up_key:
move(0, -1);
break;
case down_key:
move(0, 1);
break;
case left_key:
move(-1, 0);
break;
case right_key:
move(1,0);
break;
default:
return false;
}
像这样的东西:
move( (c==right_key) - (c==left_key) , (c==down_key) - (c==up_key) );
您可以随意地用更整洁的单行代码替换这17行长的代码。
你不能,因为语言不是这样工作的。例如,如果up_key
、down_key
、right_key
和left_key
都相等,会发生什么?
因为switch
语句只能取常量,所以在读取代码时,您知道要比较的东西都是常量。另一方面,您可以使用if
语句(或其他结构)与变量进行比较:
if (c == up_key) {
move(0, -1);
} else if (c == down_key) {
move(0, 1);
} else ...
这提供了一个明显的结构差异,可以极大地帮助后面的人阅读代码。想象一下,如果你必须查找每个case
标签,看看它是否是一个变量?
我相信这是因为编译器生成了一个带有硬编码值的跳转表,尽管我可能错了。生成表格的方式不允许这样做。
由于其他答案已经涵盖了出现错误的原因,因此有一种方法可以在按键时向四个方向之一移动:使用查找表而不是条件/开关。
设置部分:
std::map<char,pair<int,int> > moves;
moves[up_key] = make_pair(0, -1);
moves[down_key] = make_pair(0, 1);
moves[left_key] = make_pair(-1, 0);
moves[right_key] = make_pair(1, 0);
功能:
bool Character::keyPress(char c) {
if (moves.count(c)) {
pair<int,int> dir = moves[c];
move(dir.first, dir.second);
return true;
} else {
return false;
}
}
//here is the full functional code snippet which can be compiled and run with most of C++
//compiler/link ...console app was demoed but you can apply the code/logic to win32 app...
//if you have any problem, send me email to Samuel_Ni@yahoo.com
#include <iostream.h>
#include <map>
#include <conio.h>
class CkbdHanler{
private:
map<char,pair<int,int> > moves;
protected:
char up_key;
char down_key;
char right_key;
char left_key;
public:
CkbdHanler(char a,char b,char c,char d):up_key(a),
down_key(b),
right_key(c),
left_key(d)
{
moves[up_key] = make_pair(0, -1);
moves[down_key] = make_pair(0, 1);
moves[left_key] = make_pair(-1, 0);
moves[right_key] = make_pair(1, 0);
}
bool keyPress(char c){
if (moves.count(c)) {
pair<int,int> dir = moves[c];
move(dir.first, dir.second);
return true;
} else return false;
}
void move(int i,int j){
cout<<"(i,j)=("<<i<<","<<j<<")"<<endl;
}
};
int main(int argc, char* argv[])
{
CkbdHanler CmyKbdH('u','d','l','r');
cout << "Hello C++... here is a demo of Map to replace switch-case" << endl;
CmyKbdH.keyPress('d');
cout << endl << "Press any key to continue...";
getch();
return 0;
}
相关文章:
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- 表达式必须具有常数值,变量不能用作定义数组大小的常数
- 变量不能明确
- 流变量不能出现在 OpenMP 第一私有中?
- 为什么 UInt64 变量不能包含大于 UInt32::Max 的值?
- 变量不能在 lambda 中隐式捕获,并且没有使用 switch 语句指定捕获默认值
- 什么形式上保证了非原子变量不能看到凭空出现的值,并像理论上原子一样创造数据竞赛?
- 为什么可以将Char指针变量初始化为字符串,而INT指针变量不能初始化到整数数组
- clang vs gcc CRTP:constexpr 变量不能有非文字类型
- 为什么这些变量不能移动?
- 为什么我的基类指针变量不能访问派生类中的函数?
- 变量不能出现在常量表达式中
- 哪些临时变量不能在 c++11 中使用“someType()”初始化
- 为什么除了直接赋值0之外,bool变量不能设置为0
- 常量变量不能是引用的模板参数,但非常量可以
- WARN:变量不能绑定(它要么不存在,要么已经被优化掉了)
- 整型变量不能存储大的值
- 变量不能在没有指定capture-default的lambda中隐式捕获
- 变量不能产生正确的数据