Thread: Access to derived functions

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    43

    Access to derived functions

    Hi all

    Got a problem I constantly run into when creating small games as programming practice. I am currently practicing keeping the game engine seperate from the game itself, passing the specific game into the engine so the latter can do its thing.

    The problem I have is that when creating the Engine's functions, because I want it to process any game I throw at it, I have to use the parent class "Game" as the parameter being passed into the engine, instead of the specific game such as "Connect 4" or "Checkers". In so doing I lose all the functionality of the specific game when passing it into the engine.

    Consider the following fragments that should demonstrate my problem:

    Code:
    Connect4 C4Game; // The Game I will pass into the engine. Connect4 is a derivation of the Game class 
    
    Engine::PlaceCounter(Game& theGame) // A function in the engine to place counters in whatever game is passed in
    {
    unsigned short WhereToPlaceCounter;
    cout << "Please choose where to place counter: ";
    cin >> WhereToPlaceCounter;
    theGame.CheckPlacementPossibility();
    //...
    }
    I would like "CheckPlacementPossibility" to check with the specific game we've passed in that it's OK to place the counter where the user has requested (since where we can place a counter on the Connect 4 grid will be different to where we can place it on the Othello grid, for example). However, the complier refuses - instead it calls the CheckPlacementPossibility function straight from the parent class Game, where I have a statement that simply reads "you shouldn't be chaining this far up!". I would like the function to call CheckPlacementPossibility ()according to whichever type of Game I've passed in (such as Connect 4).

    As I've said I seem to run into this problem all the time and working around it tends to be ugly, legnthy, and often compromises what I originally set out to achieve. If anyone knows of a simple way to resolve this it would be greatly appreciated.

    Thanks :-)
    Last edited by Know_Your_Role; 12-11-2009 at 06:03 AM.

  2. #2
    Registered User
    Join Date
    Mar 2009
    Posts
    43
    Sorry I should've mentioned that - yes I have. But it's as though C4Game has been converted into an object of type Game, and as such it is using all the functions local to that class.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Know_Your_Role
    But it's as though C4Game has been converted into an object of type Game, and as such it is using all the functions local to that class.
    That sounds like type slicing. If you use sufoode's suggestion, and also make sure that (smart) pointers or references to Game are used, then this problem should not happen.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    post more code.

  5. #5
    Registered User
    Join Date
    Mar 2009
    Posts
    43
    I've managed to fix this issue but am having a similar issue. I have placed it under a seperate post, but a summary here: In "main" I am creating game objects of various types (Connect4, chess etc) with a view to plugging them into the same generic "Game" engine ("Game" being the base class of the various sorts of game we may plug into the engine). So I may use the following:

    Code:
     
    Engine* theEngine = new Engine;
    Connect4* C4Game = new Connect4; // the constructor allocates the member data
    theEngine->RunSinglePlayer (C4game); 
    
    void theEngine::RunSinglePlayer (Game* RelevantGame)
    The data is not passing over from the call to RunSinglePlayer() and the actual function. I can only assume this is because the type of data is now the base class Game instead of derived class Connect4. However this will not work for what I am trying to achieve. Whilst I need the call to RunSinglePlayer() to allow for various different sorts of games which may be plugged into the engine, I still need it to use the object's function calls and member data which would be relevant if were still a Connect4 object.

    I don't even know if this is possible but I certainly hope so because this is going to cause a massive problem if not If you know a workaround I'd really appreciate - thanks!

    However because it is being converted from

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Engine::PlaceCounter(Game& theGame)
    This looks like a design flaw to me. If the engine is indeed separate from the game then keep them that way. Why does the engine need to know about the game at all? The game could derive from something like IGame to facilitate different type of games in the future. The derived versions of IGame would then use IEngine instead of IEngine using IGame. The game should use the engine, not the other way around.


    IGame
    - Checkers
    - Tic tac toe
    - ...
    IEngine
    - raw Direct3D
    - raw OGL
    - OGRE
    - Irrlicht
    - Unreal
    - Quake
    - ...

    It is not simple to abstract this out b/c Unreal, Quake, Direct3D, OGL, etc are all very different. However it is possible to find some commonalities between them that could be applied to all generic 'engines' or rendering 'engines'.

    Might I recommend the following book:
    http://www.amazon.com/Game-Engine-Ar.../dp/1568814135
    Last edited by VirtualAce; 12-12-2009 at 01:04 PM.

  7. #7
    Registered User
    Join Date
    Mar 2009
    Posts
    43
    Bubba - So you're saying the engine should plug into the game, not the other way round? Ironically this is how I first set this up before deciding it didn't look right!

  8. #8
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I'm saying the game should 'use' the engine. Nothing says it has to plug-in in the sense of passing a pointer to the engine. Now if you were to use a game interface pointer it wouldn't be as bad but there is still no reason to pass any core 'game' pointers to the engine in that manner.

    Much of the communication back and forth can be done by either implementing engine interfaces that have no impl or are designed to be user implemented or by callbacks from the engine.

    I would invite you to look at the lightweight rendering 'engine' called OGRE as an example of what I'm talking about. Now this is not the only design out there but I would feel comfortable in saying that most 'engines' operate in a similar fashion. If you have a couple hundred dollars you can buy a license to Torque and see how it is implemented. There are many more samples on the internet on how to structure your core engine and the game using it. I highly recommend buying several books on the topic before getting too far into code. I usually follow a pattern of design, then code, then more design, then more code. A pure waterfall approach has not worked for me so I use a 'stepped' waterfall that is more akin to something like Sprints in Agile dev. The core principle is that you must have some kind of design be it textual or UML before you begin coding or you will end up with issues like the one you are encountering.

    What you decide to do from this point on can and probably will make or break the rest of your project. I invite you to take a step back from the code and look at the bigger picture. Do not be so concerned with the implementation as much as the design at this point. If you do not have a design then you will end up re-implementing code over and over and over. So before you move on scope out your project and find out what it's core goals are and how you plan to meet those goals. Even though this is probably a hobby project software engineering practices still apply and will help you later. If I really did not want you to succeed I would just give you answers to your problem instead of giving you some guidance about doing some design work before continuing. So take a few days and start drawing boxes here and there and come up with a rudimentary design for the system. Remember you aren't designing every little aspect of it here - just the core pieces and how they will interact with one another is sufficient at this time. When you get stuck you can then come back and ask some design related questions which many here will be able to assist you with.
    Last edited by VirtualAce; 12-15-2009 at 12:33 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. An array of macro functions?
    By someprogr in forum C Programming
    Replies: 6
    Last Post: 01-28-2009, 07:05 PM
  2. Replies: 7
    Last Post: 11-17-2008, 01:00 PM
  3. derived class can not access base class protected member?
    By George2 in forum C++ Programming
    Replies: 2
    Last Post: 10-21-2007, 06:32 PM
  4. Passing pointers between functions
    By heygirls_uk in forum C Programming
    Replies: 5
    Last Post: 01-09-2004, 06:58 PM
  5. virtual functions and templates
    By ygfperson in forum C++ Programming
    Replies: 7
    Last Post: 07-22-2003, 01:10 PM