C++: How to pass user input through the system without using global variables?

后端 未结 1 611
时光取名叫无心
时光取名叫无心 2020-12-11 14:14

I am having the problem, that my application can has a lot of user input which determines how the application will be run. The application is an in memory database system an

相关标签:
1条回答
  • 2020-12-11 14:31

    How to pass user input through the system without using global variables.

    It is easy. Surprise, I created a class.

    For a while, I called this class a travel case, because I considered it analogous to the needs of a suitcase during a trip. The TC_t is a non-standard container which held useful things for what is going on at your destination, and there is only one created, with references passed to any other objects that could use the information. Not global, in the strictest sense.

    This TC_t is created in main() thread, while studying the command line options.


    I recently wrote yet-another-game-of-life. User inputs included a) destination of output (i.e. a tty num), b) initial fill-pattern choices, c) 'overrides' for game board dimensions, d) test modes, including max speed, and vector vs. array options for cell behaviours.

    The GOLUtil_t (Game Of Life Utility) (previously TC_t) includes methods that are useful in more than one effort.

    For your question, the two typical globals I avoided are the a) gameBoard, and b) ansi terminal access.

    std::cout << "accessing '" << aTermPFN << "' with std::ofstream " 
              << std::endl;
    std::ofstream*  ansiTerm = new std::ofstream(aTermPFN);
    
    if (!ansiTerm->is_open())
    {
       dtbAssert(nullptr != ansiTerm)(aTermPFN);
       std::cerr << "Can not access '" << aTermPFN << "'" << std::endl;
       assert(0);  // abort
     }
    
    // create game-board - with a vector of cell*
    CellVec_t  gameBoard;
    gameBoard.reserve (aMaxRow * aMaxCol);
    
    GOLUtil_t  gBrd(aMaxRow, aMaxCol, gameBoard, *ansiTerm);
    

    This last line invoked the ctor of GOLUtil_t.

    The instance "gBrd" is then passed (by reference) to the ctor of the game, and from there, to any aggregate objects it contained.

    std::string retVal;
    {
      // initialize display, initialize pattern
      GameOfLife_t  GOL(gBrd, timeOfDay, fillPatternChoiceLetter, useArray);
    
      std::string retValS = GOL.exec2(testMode);
    
      retVal = gBrd.clearGameBoard(retValS); // delete all cells
    }
    // force GameOfLife_t dtor before close ansiTerm
    
    ansiTerm->close();
    

    Summary - No globals.

    Every instance of any class that needed this info (where to output? what are dimensions?) has access to the GOLUtil_t for their entire lifetime. And GOLUtil_t has methods to lighten the coding load.

    Note: because single output terminal, I used a single thread (main)


    Your first refactor effort might be to:

    a) remove the global classes,

    b) and instead instantiate these in main() (for lifetime control)

    c) and then pass-by-reference these formerly global instances to those non-global objects that make use of them. I recommend in the ctor(s).

    d) remember to clean up (delete if new'd)


    my environment: Ubuntu 15.10, 64 bit, g++ V5

    0 讨论(0)
提交回复
热议问题