为什么我不能在switch-case语句中有变量?

时间:2012-01-19 04:03:25

标签: c++ switch-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。

7 个答案:

答案 0 :(得分:15)

如错误消息所述,case表达式必须是常量。编译器在编译时将其构建为一个非常快速的查找表,如果程序运行时值可能会发生变化,则无法执行此操作。

如果你确实需要它们是变量而不是常数,那么你最好的选择是使用if / else语句。

答案 1 :(得分:7)

替换这个长笨拙的代码,

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行长的代码。

答案 2 :(得分:1)

你不能因为语言不能这样做。例如,如果up_keydown_keyright_keyleft_key都相同,会发生什么?

答案 3 :(得分:1)

因为switch语句只能使用常量,所以在读取代码时,你知道你所比较的东西都是常量。另一方面,您可以使用if语句(或其他一些结构)来比较变量:

if (c == up_key) {
    move(0, -1);
} else if (c == down_key) {
    move(0, 1);
} else ...

这提供了明显的结构差异,可以极大地帮助那些在您阅读代码之后的人。想象一下,如果你必须查找每个case标签,看看它是否是一个变量?

答案 4 :(得分:1)

我相信这是因为编译器会生成一个跳转表,其中的值是硬编码的,尽管我可能错了。生成表的方式不允许。

答案 5 :(得分:1)

由于其他答案已经涵盖了您收到错误的原因,因此可以采用四种方向之一移动以响应按键:使用查找表而不是条件/开关。

设置部分:

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;
    }
}

答案 6 :(得分:0)

//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;
}