Subclass pointer allocation (C ++)

I am developing a game, and I need to find a way to get the value of a specific “map block” in the game (in char format). I have a DisplayableObject class that takes care of all the sprites and a subclass of ThreeDCubePlayer that takes care of the player object. For ease of rendering / updating, all DisplayableObjects are stored in an array with the 0th cell containing the player (which is of type ThreeDCubePlayer). ThreeDCubePlayer has another DisplayableObject constructor (it takes two additional arguments), and only ThreeDCubePlayer has the GetMap () functions that I need. So here is what I have done so far:

ThreeDCubePlayer* cubePlayer = &((ThreeDCubePlayer &)m_ppDisplayableObjects[0]); char mapEntry = GetMapEntry((int)*(cubePlayer->GetMapX()), (int)*(cubePlayer->GetMapY())); 

This is part of the ThreeDCubeGame.cpp function (the function that controls the input of the card and keyboard). The problem I am facing is that both of these lines, when compiled, give an "illegal indirection" error. I thought this error occurs when I try to dereference something that is not a pointer, and I'm sure that cubePlayer looks like a pointer ...

Does anyone have an idea what should I do?

+4
source share
7 answers

Use one of the safe type operations, for example. dynamic_cast instead of C-style.

If m_ppDisplayableObjects is DisplayableObject **, then it will look something like this:

 ThreeDCubePlayer* cubePlayer = dynamic_cast<ThreeDCubePlayer*>(m_ppDisplayableObjects[0]); if (cubePlayer != NULL) { char mapEntry = GetMapEntry(cubePlayer->GetMapX(), cubePlayer->GetMapY()); } else // Not a ThreeDCubePlayer* ... 
+4
source

A few suggestions:

Do not use C-style casts, use appropriate C ++ instead. In your case, when you abandon the inheritance hierarchy, you should use dynamic_cast instead of throwing a C-style sledgehammer. This will entail a slight lack of runtime, but will also make anything safe because it is not going to do anything unpleasant behind you simply because you are treating a piece of $ deity_knows_what as a three-document player. Assuming your m_ppDisplayableObjects array actually contains pointers, it will look like this:

 ThreeDCubePlayer *cubePlayer = dynamic_Cast<ThreeDCubePlayer *>(m_ppDisplayableObjects[0]) if (cubePlayer) { // Important, if you don't check for 0 here you might dereference a null pointer ... cubePlayer->GetMapX() ... 

Also, if you need to pass the result to GetMapX, then you will have an impedance mismatch that you must find elsewhere; I would recommend either setting up the GetMapX return type, or the parameters passed to GetMapEntry. As a rule, the need to throw madly - this is a sign of a design problem - well-designed C ++ code should not require many castings, and especially not many C-style applications.

+3
source

Your trick is wrong, and I think the second line does not require any throw (it depends on how the methods are defined).

It should be:

 ThreeDCubePlayer* cubePlayer = (ThreeDCubePlayer*)m_ppDisplayableObjects[0]; char mapEntry = GetMapEntry( cubePlayer->GetMapX(), cubePlayer->GetMapY() ); 

The cast in the first line should also be a C ++ style, for example:

 ThreeDCubePlayer* cubePlayer = static_cast<ThreeDCubePlayer*>(m_ppDisplayableObjects[0]); 
+1
source

For the first row, you can use DisplayableObject for the DisplayableObject derived class using dynamic_cast .

 ThreeDCubePlayer* cubePlayer = dynamic_cast<ThreeDCubePlayer*> (m_ppDisplayableObjects[0]); 

In the second line, you play everything that ThreeDCubePlayer::GetMapX() returns. If this function does not return a pointer (or some class with an overloaded * operator), you will get a compilation error.

+1
source

Remember that in a game application, when the situation ends with you making zillions dynamic_casts for the game frame, it can negatively affect performance. You will usually find that people make other decisions to determine how to convert the object pointer stored in the container to the appropriate object type using static_cast or C style casting instead of relying on RTTI. Depending on the number of object types and other factors, there are various ways to do this, but the simple method is only to have an enum class identifier and a get method for each of the enumeration types, which returns null if the class identifier doesn’t match the request .

+1
source

You did not specify a lot of code, but I think your first line should be:

 ThreeDCubePlayer* cubePlayer = (ThreeDCubePlayer *) m_ppDisplayableObjects[0]); 

We need to see the GetMapX () declaration to find out about the second line.

0
source

ppDisplayableObjects is an array or base pointers, right? so try this?

 const ThreeDCubePlayer* const cubePlayer = m_ppDisplayableObjects[0]; char mapEntry = GetMapEntry( cubePlayer->GetMapX(), cubePlayer->GetMapY() ); 

GetMapX etc. should return (unsigned) int? and not a pointer to int? (no negs? so unsigned?)

I would like all other comments on casting to be added, they are a sign that your hierarchy is not working correctly, but ... but if you need to quit, then think about which C ++ casting you will need for Using this is a useful exercise, it also means that if you want to revise / tighten your code, all throws are easier to search and delete.

ps - create your constant where you can and add arrays, etc. to some kind of owner class, possibly singleton, if you know that you only have

also IMHO ... (sorry) write yourself a Coords class so you can do something like GetMapEntry (const Coords and coords) instead of getting the x and y values ​​separately, it will save you when you exchange them the wrong way and etc. :)

0
source

All Articles