C ++ - 不改变的类私有变量

时间:2018-02-08 19:08:35

标签: c++ sdl-2

我已经用C ++编程了一段时间,并且正在使用SDL2库来制作游戏。不幸的是,该播放器的类具有仅在方法中更改的变量,然后不会更新以供以后使用。

部首:

class playerChar {
public:
     void move();
     void handleInput(SDL_Event& lEvent);
     void render();
     int getValX();
     int getValY();
     playerChar();
private:
     int pPosX, pPosY;             //Pos and Direction arent changing
     int pDirectionX, pDirectionY;
     //Posion and Direction (direction. Has value -1, 0 or 1)
     static const int pVel = 10;
     static const int pHeight = 10, pWidth = 10;
     eTexture playerTex;
};

cpp文件:

playerChar::playerChar(){
     pPosX = 0;
     pPosY = 0;
     pDirectionX = 0;
     pDirectionY = 0;
     playerTex.loadFile("playerIMG.png");
}

void playerChar::handleInput(SDL_Event& lEvent){
     //Key Pressed
     if(lEvent.type == SDL_KEYDOWN && lEvent.key.repeat == 0){
          switch(lEvent.key.keysym.sym){
               case SDLK_UP:
               pDirectionY = -1;
               break;
               case SDLK_s:
               pDirectionY = 1;
               printf("%i\n", pDirectionY);
               break;
               case SDLK_d:
               pDirectionX = 1;
               break;
               case SDLK_a:
               pDirectionX = -1;
               break;
               default:
               break;
          }
     }
     //Key Released
     else if(lEvent.type == SDL_KEYUP && lEvent.key.repeat == 0){
          switch(lEvent.key.keysym.sym){
               case SDLK_w:
               pDirectionY = 0;
               break;
               case SDLK_s:
               pDirectionY = 0;
               break;
               case SDLK_d:
               pDirectionX = 0;
               break;
               case SDLK_a:
               pDirectionX = 0;
               break;
               default:
               break;
          }
     }
}

void playerChar::move(){
     //printf("pos:%i, vel:%i, dir:%i\n", pPosY, pVel, pDirectionY);
     pPosX += pVel*pDirectionX;
     pPosY += pVel*pDirectionY;
     //If Direction is + then it adds velocity
     //If Direction is - then it subtracts
     //If Direction is 0 then adds nothing
     //printf("%i, %i\n", pDirectionX, pDirectionY);
}

void playerChar::render(){
     playerTex.render(pPosX, pPosY);
}

int playerChar::getValX(){
     return pDirectionX;
}

int playerChar::getValY(){
     return pDirectionY;
}

我一直用printf()s检查它们的值(它只是main()中使用getValX / Y()方法的printf())。 handleInput()内部的一个显示它在方法中已经改变,但是每帧运行的那个表示它仍然是0.我主要测试按s。

我试过让handleInput()方法返回值,然后创建一个set方法但是没有修复它。

我看了很多网站和论坛以及一位经验丰富的朋友,他也很难过,也无法解决问题。任何帮助是极大的赞赏。

修改
对不起,如果我太模糊,我试图保持简洁。 ONLY上方的cpp包含playerChar类的方法 Main()中的实际实现是

int main(int argc, char* args[]) {
//irrevelvant to question

playerChar player;
while(!quit) {
          fpsTimer.start();
          quit = eInputCheck(event, player);

          if(fpsTimer.getTicks() < ticksPerFrame) {
               SDL_Delay(ticksPerFrame - fpsTimer.getTicks());
          }
          SDL_RenderClear(gRenderer);

          //Render new frame here
          player.move();
          player.render();
          printf("%ix, %iy\n", player.getValX(), player.getValY());
          SDL_RenderPresent(gRenderer);
     }
     eClose();
     return 0;
}  

eInputCheck()来自controls.cpp

bool eInputCheck(SDL_Event event, playerChar player){
     while(SDL_PollEvent(&event) != 0){
          player.handleInput(event);
          if(event.type == SDL_QUIT){
               return true;
          }
     return false;
}

我试图使pDirectionX / Y为方向变为1 / -1并使0静止。问题在于,即使按住按钮,当我在main中调用getValX / Y方法时,它似乎也不会改变。

终端在运行时显示如此,我按下s:

0x, 0y
0x, 0y
0x, 0y
0x, 0y
0x, 0y
0x, 0y
0x, 0y
1        //The printf() from inside the handleInput() method
0x, 0y
0x, 0y
0x, 0y
0x, 0y

它甚至在按住按钮的同时给出了这个。 (我按ESC结束程序)

1 个答案:

答案 0 :(得分:1)

您将COPY传递给eInputCheck,此副本在进入函数时构建。您按值传递playerChar

就像这样

playerChar otherOne = player; // Copies the player to the variable otherOne using a "copy constructor"

C ++中有很多案例,它是一种非常丰富的语言。

playerChar otherOne = player;   // Copies the player (said before).

playerChar &reference = player; // Reference is now refers to otherOne,
                                // a change on reference is reflected
                                // on player.

otherOne = player;              // otherOne was initialized before,
                                // so copy constructor is not called
                                // But a copy assignment is called instead

reference = otherOne;           // Reference was set before to refer to
                                // player, so, a "copy assignment" is
                                // called. Because references always
                                // refers to the same object
                                // initialized with. So, C++ solves this
                                // by copying the otherOne to the object
                                // refered by reference, using a copy 
                                // assignment operator

这是C ++中最令人困惑和困难的部分之一。

你有两个解决方案,

  1. 现代解决方案(我认为在性能方面不利于C ++),不变性,尝试从eInputCheck返回一个新的播放器实例。

  2. 第二种解决方案是将参考传递给eInputCheck

  3. 请重新定义eInputCheck,如下所示:

    bool eInputCheck(SDL_Event &event, playerChar &player){
        while(SDL_PollEvent(&event) != 0){
            player.handleInput(event);
            if(event.type == SDL_QUIT){
                return true;
            }
        return false;
    }
    

    这会将引用传递给您的函数。 请阅读此内容:

    Reference concept in C++

    Passing arguments by reference

    Copy constructor

    Copy assignment