Sign in to follow this  
Darragh

Polymorphic questions in C++

Recommended Posts

Hi everyone. I'm currently working on a little asteriods game in C++ for an assignment and I'm having a little trouble with polymorphism. I've got my classes and all planned in UML diagrams, however there are two issues i need to clear up: My first question is how to check if an abstract or 'virtual' function as C++ calls it is implemented. I have a generic class called 'GameObject' which describes some basic properties common to all the objects in the game. There are also abstract functions which may or may not be implemented and by default the pointers to these functions are set to 0 or NULL which indicates they are not implemented. The game loop cycles through all the objects in the game then and calls abstract functions where implemented:
/*******************************************************************************

Name:       Game::event_gameLoop
Purpose:    Gets each object to do its move etc.. and does collision checking
            for each object that has explicitly stated a collision event
Parameters: none
Returns:    none

*******************************************************************************/

void Game::event_gameLoop ( void )
{
     // Iterate through the objects array and process the gamestate of each object
     
     for ( int i = 0 ; i < MAX_OBJECTS ; i++ )
     {
         // Get the current object pointer from the array
         
         GameObject * currentObject = objects[i];
         
         // If this object is NULL then continue to next iteration
         
         if ( currentObject == NULL ) continue;
         
         // Move the object if it has a move event ( this line won't work ! )
         
         if ( currentObject->event_move != NULL ) currentObject->event_move();
         
         /* Call Collision checking and check offscreen routines here... */
         
            // TODO
         
         // Draw the object if it has a draw event ( this line won't work ! )
         
         if ( currentObject->event_draw != NULL ) currentObject->event_draw();
         
     }

}

The above code won't compile though: the GCC compiler tells me 'invalid use of member (did you forget the `&' ?) ' for the lines indicated that are not working. Bascially I want to know how to check if a function has an implementation or not. I tried using the & operator as it suggested but it wouldn't work either. Any suggestions ? You might say well why not provide a default, blank implementation of the function and just call it without worrying if it exists or not. This would work but wouldn't be very efficient. I plan on defining events that are called when a collision or such happens, and if no collision event is defined then there should no collision checking performed, thats the plan anyway- so you can see why i need to do the above.. Ok my second question again is related to virtual functions. Part of the assignment is to get the game data saving and loading from a file. I'm looking for the best (or simplest for that matter) way to do this for all objects in the game so i've came up with the following plan:
function gameSave:
   
   for each object in the game:
        
        if virtual function implemented: call someObject::save

   end for

end function


function gameLoad:

   until end of file

       read size of next object (integer)
       allocate enough space for object in memory
       read size bytes into the address of the block allocated
       add address of new game object somewhere in gameobject array       

   end until

end function

function SomeObject::save
 
   write size of the class to the file
   write entire class data to the file  

end function  


Ok so this seems like a simple enough idea. Each objet will be responsible for saving its own data and when the game goes to load objects it wont need to know what they are just how big they are and add them into the game. Problem though: could the function pointers for the virtual functions ( which would get saved along with the other class data ) be invalid the next time the game runs ? This is something i'm not sure of. Windows talks of a 'virtual' address space for each program, so is the pointer to the abstract function merely an offset within this address space ( in which case it would probably remain constant between several runs ) or is it an actual physical address- which would make it impossible to predict each time the program runs ? Sorry for all these questions, but these two elements are very important to my design so if I could get them working I would be very grateful. Cheers, Darragh

Share this post


Link to post
Share on other sites
You can't instantiate a class which has abstract/pure virtual functions, so the problem doesn't arise (there are exceptions, for example you can call a pure virtual from a constructor of a abstract base class - this will result in a run-time error).

So, the simple answer to your question is:

if virtual function implemented: call someObject::save


Is redundant, as every GameObject child class must implement save - else it can't be created.


Perhaps what you want to do can be achieved by having a default save() funciton on GameObject that does nothing.

Share this post


Link to post
Share on other sites
Quote:
Original post by Darragh
My first question is how to check if an abstract or 'virtual' function as C++ calls it is implemented.


I assume what you mean is pure virtual. You don't need to make checks, a class with at least one pure-virtual member function is an abstract class and therefore non-instantiable if you try you'll get caught out at compile-time so it's impossible to make a direct call on virtual member function through a reference/pointer to base type that refers to an instance that is a sub-type that doesn't have an implementation of the method.

Quote:
Original post by Darragh
The above code won't compile though: the GCC compiler tells me 'invalid use of member (did you forget the `&' ?) ' for the lines indicated that are not working. Bascially I want to know how to check if a function has an implementation or not. I tried using the & operator as it suggested but it wouldn't work either. Any suggestions ?


As i said earlier you don't need to make a check, without knowing the exact type of objects i'm assuming objects is either of type GameObject (&objects)[N] (an array of GameObject) or of type GameObject* that refers to a (dynamically allocated) array. Now you have two problems here, first i'll get to your compile-error:

currentObject is a pointer to GameObject, an element of an array of GameObject is a reference to GameObject not a pointer.

In which case either you do:

A. Take the address of the element.

GameObject* currentObject = &objects[i];


B. Use a (constant) reference instead of a pointer and change -> to .


GameObject& currentObject = objects[i];


Now if this is the case then you most probably have another problem, object slicing problem and no dynamic dispatch (dynamic binding). In which case you'll need an array of pointers to GameObject.

Share this post


Link to post
Share on other sites
Quote:
Original post by Darragh
My first question is how to check if an abstract or 'virtual' function as C++ calls it is implemented.

You don't. If you have an instance of a class with a virtual member function then the virtual member function is implemented. If the virtual member function isn't implemented then you can't instantiate an object of that class in the first place.

That said, your design seems a bit suspect. Having a base GameObject class with lots of virtual functions is usually a bad idea in C++. Prefer to split your classes up depending on functionality. You might, for example, have a collection of (smart) pointers to Moveable objects on which you will call move and a collection of (smart) pointers to Drawable objects, on which you will call draw.
Quote:
Problem though: could the function pointers for the virtual functions ( which would get saved along with the other class data ) be invalid the next time the game runs ? This is something i'm not sure of. Windows talks of a 'virtual' address space for each program, so is the pointer to the abstract function merely an offset within this address space ( in which case it would probably remain constant between several runs ) or is it an actual physical address- which would make it impossible to predict each time the program runs ?

Any pointer will likely be invalid when read like this. You need to serialize.

Σnigma

Share this post


Link to post
Share on other sites

I think the abstract class should implement the "default" functionality, that is, if you have a RenderObject virtual function in your abstract class, it should be implemented like this:

virtual bool RenderObject(int x, int y) {return(true);}

This is actually faster than check if a class has an implementation of a virtual function.

Anyway, if you still want to enforce a call to a virtual function, you should have to manually identify the class type, with some sort of virtual funcion that returns a unique class id, then, cast it to the corresponding derived class, and call the function.

Personally, and for debug purposes, if a virtual function is not meant to be called, I usually add some logging calls that warn me that the wrong function has been called.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this