How to declare and use classes

Hi Everyone,
I started a project (using the esp32) for my children . It will be a kind of ball launcher in the garden.
I implemented some classes in order to make the toy configurable:
-Ball class: to define the type of available ball types to launch (speed,orientation,..)
-Game: different games can be created based on the balls . A game can have multiple balls to launch
-GameList: all the games are stored in a list . The first draft look like this:


class Ball {
  public:
    Ball(char *ballName, int hAngle, int vAngle, int topSpeed, int bottomSpeed) {
      _hAngle = hAngle;
      _vAngle = vAngle;
      _topSpeed = topSpeed;
      _bottomSpeed = bottomSpeed;
      strcpy(_ballName, ballName);
    }
    char* getBallName() {
      return _ballName;
    }
  private:
    char _ballName[50];
    int _hAngle = 0;
    int _vAngle = 0;
    int _topSpeed;
    int _bottomSpeed;
};

class Game {
  public:
    Game(char *newName, int NBBalls, int ballInterval) {
      _numberOfBalls = NBBalls;
      _ballInterval = ballInterval;
      strcpy(_gameName, newName);
    }
    void setGameName(char *newName) {
      strcpy(_gameName, newName);
    }
    char*  getGameName() {
      return _gameName;
    }
    void setNBBalls(int NBBalls) {
      _numberOfBalls = NBBalls;
    }
    int getNBBalls() {
      return _numberOfBalls;
    }
    void setBall(Ball* newBall, int index) {
      _ballList[index] = newBall;
    };
    Ball* getBall(int index) {
      return _ballList[index];
    };
  private:
    int _numberOfBalls;
    int _ballInterval;
    char _gameName[50];
    Ball* _ballList[3] = {NULL, NULL, NULL};
};
class GameList {
  public:
    GameList() {
      _nbGame = 0;
    }
    void setGame(Game* newGame, int index) {
      _gameList[index] = newGame;
    }
    Game*  getGame(int index) {
      return _gameList[index];
    }
  private:
    Game* _gameList[3] = {NULL, NULL, NULL};
    int _nbGame;
};


GameList gameList;

void setup() {
  Serial.begin(115200);
  //------------Create all the Balls
  Ball b00 ( "b00", 0, 0, 0, 0);
  Ball b01 ( "b01", 45, 45, 0, 0);
  Ball b02 ( "b02", 90, 90, 0, 0);
  printf ("Address b00 is %p \n", &b00);
  printf ("Address b01 is %p \n", &b01);
  printf ("Address b02 is %p \n", &b02);

  //------Create 3 Games
  Game game0 ("game0", 3, 2000);
  printf ("Address game0 is %p ", &game0);
  printf ("game0 has %u balls ", game0.getNBBalls ());
  printf ("Its name is %s \n", game0.getGameName());
  game0.setBall (&b00, 0);
  game0.setBall (&b01, 1);
  game0.setBall (&b02, 2);


  Game game1 ("game1", 3, 2000);
  printf ("Address game1 is %p ", &game1);
  printf ("game1 has %u balls ", game1.getNBBalls ());
  printf ("Its name is %s \n", game1.getGameName());
  game1.setBall (&b00, 0);
  game1.setBall (&b01, 1);
  game1.setBall (&b02, 2);

  Game game2 ("game2", 2, 2000);
  printf ("Address game2 is %p ", &game2);
  printf ("game2 has %u balls ", game2.getNBBalls ());
  printf ("Its name is %s \n", game2.getGameName());
  game2.setBall (&b01, 0);
  game2.setBall (&b02, 1);


  // Here the games addresses are stored in the list
  gameList.setGame (&game0, 0);
  gameList.setGame (&game1, 1);
  gameList.setGame (&game2, 2);

  //Retrieve game 2 from gameList
  Game*  p_gameFromList = gameList.getGame (0);

  printf ("In Setup: Address game retreived 0 is %p", p_gameFromList); // It works
  printf (" has %d balls", p_gameFromList->getNBBalls()); // It works
  printf (" name is %s \n", p_gameFromList->getGameName()); // It works

  p_gameFromList = gameList.getGame (1);

  printf ("In Setup: Address game retreived 1 is %p", p_gameFromList); // It works
  printf (" has %d balls", p_gameFromList->getNBBalls()); // It works
  printf (" name is %s \n", p_gameFromList->getGameName()); // It works

}


void loop() {

  //Retrieve game from gameList
  Game*  p_game = gameList.getGame (0);

  printf ("In Loop: Address game retreived 0 is %p", p_game);
  printf (" has %d balls", p_game->getNBBalls());
  printf (" name is %s \n", p_game->getGameName());

    p_game = gameList.getGame (1);

  printf ("In Loop: Address game retreived 1 is %p", p_game);
  printf (" has %d balls", p_game->getNBBalls());
  printf (" name is %s \n", p_game->getGameName());

  Ball* p_bb = p_game->getBall(0);
  //  printf (" retreived ball address0 is %p", p_bb); Causes a reboot
  //  printf (" name is %s \n", bb->getBallName());

  while (1) {}


}

There is surely something wrong with it because after filling the gameList, I try to retrieve a game by an id.
It looks to work in the setup(), but the same piece of code in the loop gives garbage.
The memory addresses look ok , but not the game data (number of balls , gameName)

See the output :

In Setup: Address game retreived 0 is 0x3ffb1eb4 has 3 balls name is game0
In Setup: Address game retreived 1 is 0x3ffb1efc has 3 balls name is game1
In Loop: Address game retreived 0 is 0x3ffb1eb4 has 1061159565 balls name is ⸮⸮⸮?
In Loop: Address game retreived 1 is 0x3ffb1efc has 0 balls name is

Can someone tell what I do wrong ?

You created your variables in setup(), so when setup() ends, they go out of scope and are destroyed and that memory is freed.

If you make them global variables, they will work in loop() as well as setup()

If you improve your classes to check that the index you are passing is within range, you would discover that you have no elements, # of balls, etc.

Hi Faraday,
this makes sense, as you say it. Thank you
I was plan to save the different games in the flash, so they can be reused.
Is declaring all the objects globally , the best way to go ?
Thanks again.

If a variable needs to be accessed by more than one function, make it global.
If a variable is only accessed within one function, make it local to that function.

Variable scope.

That's crystal clear.
Thanks

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.