Skip to main content
GameDev.net gamedev.net
🔒 Locked

Base/Derived Class Pointers

Started by Endemoniada Jan 12, 2005 at 6:01 PM 2 replies 350+ views
Original Post
Endemoniada
Endemoniada
Hi guys, I'm having a weird problem. I'm keeping an array of pointers (base class type) and everything is fine until I add a member variable to the derived class, then I get unpredictable results (lock-ups), I really can't figure out what's going on, maybe it's the general design of my program ? Here is some code: class CEntity { int a; virtual void DoSomething()=0; }; class CRedEntity : publc CEntity { int x; // if I don't add this it's fine virtual void DoSomething(); }; Now some pointer arrays: // memory CEntity* pMemory=new CRedEntity[8]; // pointers CEntity** pRedPtrs=new CEntity*[8]; // set the pointers for(int i=0;i<8;i++) pRedPtrs=pMemory+i; // also tried =&pMemory // now I use the pointer array for everything, ex: CEntity* entity=pRedPtrs[0]; entity->DoSomething(); ... ... // actually, I create another master list of pointers for all the different colored entities: CEntity** pMasterList=new CEntity*[num_red+num_green]; // setup as first-in-last-out (ommited) // now I can loop through the whole list, regardless of entity color: for(int i=0;i; entity->DoSomething(); // or whatever ... } I really don't understand what I can be doing wrong, but as soon as I add something to the derived class it breaks. The reason I'm using the pointer arrays is for management of my entities. Does anybody see anything inherently wrong with this ? Thanks guys.
Enigma
Enigma
You can't access an array-of-derived via a pointer-to-base. Pointer arithmetic and array indexing is based on the size of the static type of the pointer, so the expression Type* pointer;pointer[3]; references the fourth entry in an array of Type sized objects. For example:
int array[2];char* pointer = (char*)array;pointer[1] = 0;

will not set the second int in the array to zero it will set the second byte to zero (expect for platforms where sizeof(int) == sizeof(char), where the second byte is the second int).
So when you do CEntity* pMemory = new CRedEntity[8]; and then access into the array using pMemory + i you are actually accessing successive CEntity sized blocks of memory. If sizeof(CEntity) != sizeof(CRedEntity) then you are not referencing the correct objects (most of the time you're not actually referencing an object at all, you're referencing somewhere in the middle of one).

Ascii diagram:
Relative sizes of CEntity and CRedEntity (example):
+--------+ +--------------+
|CEntity | |CRedEntity |
+--------+ +--------------+

Array of four CRedEntity:
+--------------+--------------+--------------+--------------+
|CRedEntity |CRedEntity |CRedEntity |CRedEntity |
+--------------+--------------+--------------+--------------+
|<- index0 ->|<- index1 ->|<- index2 ->|<- index3 ->|

Array of four CEntity:
+--------+--------+--------+--------+
|CEntity |CEntity |CEntity |CEntity |
+--------+--------+--------+--------+
|||||

Array of four CRedEntity accessed by a CEntity*:
+--------------+--------------+--------------+--------------+
|CRedEntity |CRedEntity |CRedEntity |CRedEntity |
+--------------+--------------+--------------+--------------+
|||||


Enigma

EDIT: I'll get the spacing right in the diagram eventually!
HarryW
HarryW
So, to make the code work:

// memoryCRedEntity* pMemory=new CRedEntity[8];    // pMemory is of type CRedEntity* now// pointersCEntity** pRedPtrs=new CEntity*[8];// set the pointersfor(int i=0;i<8;i++)pRedPtrs=&pMemory         // I'd stick with the array indexing syntax
Harry.
Endemoniada
Endemoniada
Hi Enigma,

Thanks for taking the time to explain that, I totally understand now. I guess I thought the compiler would know what it was pointing to.

So basically I should do this:

CRedEntity* pMemory=new CRedEntity[8];

I can still do this though, can't I:

CEntity** pPtrs=new CEntity*[8];

for(i=0;i<8;i++)
pPtrs=&pMemory;

Then get the polymorphic behavior like so:

pPtrs[0]->DoSomething(); // call the virtual function

Thanks again, I really appreciate it, I doubt I'd have figured it out tonight without your reply, I was even ready to take a day or two break because it was driving me crazy, now I can code all night :)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.