All of the functions in CUndoQueue are pass-through. One way looking at this is to consider the Interface - Implementation Pattern. One class to give the using program something to handle, and the other class actually does the work but is 'hidden' from the program. One distinct advantage is that once the Interface part is stable, any functional changes in the Implementation will not cause the rest of the program to be re-compiled.
There are only a few places that need changing in the Document class to add the undo interface. Of course the menu item 'Undo' needs to have event handlers for the OnUndo and the OnUpdateUndo events. OnUndo just calls the undo() function of the queue, apply it to the game and update the program's view. The OnUpdateUndo calls the queue's canUndo() function and uses it to enable or disable the 'Undo' menu item.
The undo queue, a pointer, is created in the Document's constructor using the value stored in the App class to determine the number of element in the queue.
The queue is initialized then in the Document's OnNewDocument. At the risk of being obvious, this means that each new game starts with an empty undo queue.
As for the mechanism of storing the game in the queue, it will proceed along the following lines;
The current game is stored in a temporary CGame variable.
The move function of CGame, selectMove() is called.
ONLY IF a valid move was done is the CGame value in the temporary variable stored in the queue. Note that valid move will include cases were the Computer or the User won.