Archived

This topic is now archived and is closed to further replies.

VThornheart

Come across a strange prob. with vectors, inheritance...

Recommended Posts

Okay, so here''s my strange problem. I have a vector of pointers to cDrawnObjects, a class I made to represent generic drawn objects. I then make an object with cEntity (which is derived from cDrawnObjects), and attempt to add a pointer to it to the vector of pointers. Since cEntity is derived from cDrawnObjects, I thought it was fair play to do such a thing... however, after a few hours of debugging I''ve narrowed it down to it being that it''s not storing the pointer correctly in the vector. Is there a way to use inherited classes'' pointers in a base classes'' vector, or will I need to find a workaround such as incorporating the derived class functionality into the base class and forgetting about inheritence all-together? Anyone who has more experience with inheritence and what can and cannot be done with it, I value your input! Thank you! =)

Share this post


Link to post
Share on other sites
There should be no problem storing a pointer to a derived class in a vector of base class pointers. This is very common practise (when travering scene graphs of any sort). Are you calling a specific constructor on the base class component fo the derived class in its initialisation list, or just relying on default construction? Is this sensible in your case? Does you base class have a destructor.. and if so, is it virtual. Only stupid questions.. but I can''t think of much else atm :S.

Share this post


Link to post
Share on other sites
Well, the problem lies not so much in construction and destruction of the objects...

Basically, the code gets down to this. That vector of pointers to cDrawnObjects is filled with a number of plain old cDrawnObject pointers (the "tile layer"), and then more are added (the "inactive layer"), and then the last batch of DrawnObjects are added (the "active layer"), however this last layer isn''t cDrawnObjects but cEntities (that inherit from cDrawnObject). I''ve brought the problem down to the bare essentials, putting just one of these active objects in the queue to be loaded... but for some reason, when I''m looking in the var viewer in the MSVC++ debugger, I can see as it loops through that it stores the address for the plain cDrawnObjects correctly, but it gets 0xabababab as the address for that one lone cEntity (0xabababab is one of the default values indicating that its'' an invalid pointer in the debugger). Of course, it crashes when it tries to draw the invalid cEntity... and this is what leads me to believe that somehow the pointer to the base class doesn''t like to point to derived versions of it.

But I''m up for listening to any alternative theories. Personally, I''m scratching my head about it. =)

Share this post


Link to post
Share on other sites
Hi,

Well this should work without problems.

vector vObjects;
vector.push_back(new cEntity);

if cEntity is indeed inherited from cDrawnObjects.

Can we see some code?

[Posted before seeing the reply]

"Life is very short, and there's no time for fussing and fighting my friend..."

[edited by - Kumppi on January 15, 2004 8:51:39 AM]

Share this post


Link to post
Share on other sites
Yes, I have another theory. I''d say that the problem is not with assigning the cEntity pointer to the vector, but the problem might be somewhere else further up the line. Maybe allocation is screwing everything up. Or maybe as you are passing the address of cEntity down the pipe, you are messing with it somehow.

Maybe a little code would help us help you

| C++ Debug Kit :: GameDev Kit :: DirectX Tutorials :: 2D DX Engine | TripleBuffer Software |
| Plug-in Manager :: System Information Class :: D3D9 Hardware Enum | DevMaster :: FlipCode |

Share this post


Link to post
Share on other sites
Wait, you can do that with the vector? I thought using new gave you a pointer to an object..?

Aye, I figured it out in the method I explained above there... going through the debugger... but here''s a code snippet... hope it helps! =)

The function you see here is a method of a cWorld class I made... basically it holds a lot of vectors of pointers to drawn objects and methods like these to manipulate the world.

The problem comes up in the third loop down, when it gets to processing active objects... that''s when it returns the 0xabababab as the address, even though it finds a valid object.


// -------------------------------------------------------------

// UpdateScreenPositions() Method

// -------------------------------------------------------------

// This function will go through each object in screen radius and run its''

// UpdateScreenPosition routine, running through one layer at a time

// and adding them to vp_drawnScreenObjects, so that the vector is in

// layer order for drawing.


int cWorld::UpdateScreenPositions()
{
// We have four layers to loop through:

// Tile, Inactive, Active, and Foreground layers, in that order.

// Make a temp variable to hold the size of whatever layer we''re in.

// We will change its'' value after every layer.

int intTempSize = 0;
// Also, create a cPosition and give it the value of the screen center.

cPosition posCenter;
posCenter = this->GetScreenCenter();
// Clear the Onscreen vector.

this->vp_drawnScreenObjects.clear();
// Begin by looping through the tile layer.

intTempSize = (int)this->vp_drawnTileLayer.size();
for(int intTileCounter = 0; intTileCounter < intTempSize; intTileCounter++)
{
// Do the update. If the tile is onscreen (1 returned),

// add a pointer to it to the vector.

if (this->vp_drawnTileLayer[intTileCounter]->UpdateScreenPosition(&posCenter) == 1)
{
// The tile is on screen. Add it to the vector.

this->vp_drawnScreenObjects.push_back(this->vp_drawnTileLayer[intTileCounter]);
}
}
// Loop through the Inactive layer.

intTempSize = (int)this->vp_drawnInactiveLayer.size();
for(int intInactiveCounter = 0; intInactiveCounter < intTempSize; intInactiveCounter++)
{
// Do the update. If the inactive object is onscreen (1 returned),

// add a pointer to it to the vector.

if (this->vp_drawnInactiveLayer[intInactiveCounter]->UpdateScreenPosition(&posCenter) == 1)
{
// The inactive object is on screen. Add it to the vector.

this->vp_drawnScreenObjects.push_back(this->vp_drawnInactiveLayer[intInactiveCounter]);
}
}
// Loop through the Active layer.

intTempSize = (int)this->vp_drawnActiveLayer.size();
for(int intActiveCounter = 0; intActiveCounter < intTempSize; intActiveCounter++)
{
// Do the update. If the Active object is onscreen (1 returned),

// add a pointer to it to the vector.

if (this->vp_drawnActiveLayer[intActiveCounter]->UpdateScreenPosition(&posCenter) == 1)
{
// The active object is on screen. Add it to the vector.

this->vp_drawnScreenObjects.push_back(this->vp_drawnActiveLayer[intActiveCounter]);
}
}
// Loop through the Foreground layer.

intTempSize = (int)this->vp_drawnForegroundLayer.size();
for(int intForegroundCounter = 0; intForegroundCounter < intTempSize; intForegroundCounter++)
{
// Do the update. If the foreground object is onscreen (1 returned),

// Add a pointer to it to the vector.

if (this->vp_drawnForegroundLayer[intForegroundCounter]->UpdateScreenPosition(&posCenter) == 1)
{
// The Foreground object is on screen. Add it to the vector.

this->vp_drawnScreenObjects.push_back(this->vp_drawnForegroundLayer[intForegroundCounter]);
}
}
// All of the layers have been looped through, had screen updates, and

// if even partially onscreen, have been added to the onscreen layer.

// Now exit with success.

return 1;
}

Share this post


Link to post
Share on other sites
Just to clarify.


vector<cDrawnObjects*> vObjects;
vObjects.push_back(new cEntity);


God I hope the above works.

"Life is very short, and there's no time for fussing and fighting my friend..."

[edited by - Kumppi on January 15, 2004 9:01:24 AM]

Share this post


Link to post
Share on other sites
Ah... phew, you had me worried there... I was worried that I''d redesigned everything for no reason. =)

Well, rofl x 1000000... I tweaked the incrementing, and now it works. For some reason, I was going one too high in my for loop. Bah, humbug! =)

Thank you all for the info & help though, it was kind of you to take your time to help me out with my frustration =)

Share this post


Link to post
Share on other sites
If you are using an STL vector.. it is wise to use the iterators to step through them. They are the most uniform (wrt other containers) and reliable method of stepping through a vector. Note also that you can make const vector iterators if you wish to read only.

Share this post


Link to post
Share on other sites
Hmm, interesting... is it faster to read through? I''m going to have to read up on that... I''ve never used a vector as much more than a glorified array, and as such I never really did any reading on iterators... but it sounds like it could be very useful...

Share this post


Link to post
Share on other sites