Jump to content
  • Advertisement
Sign in to follow this  
Vero

Polymorphism and pointer arrays in c++

This topic is 2245 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So, I haven't been able to find a good explanation on this.

I want a dynamic size to my array, basically then I read in the level it tells me how many objects I need so I do the following:

MObject *objects = new MObject[num_of_obj];

after I find out how many I need through the text file I created that's reading in the level, I find out what KIND of MObjects they are so one of them is a SpeedBoost obj (inherits MOBject)

*(object+obj_counter)= SpeedBoost(args...);

for simplicity sake objcounter is 0 for now

MObject has
virtual Draw();

SpeedBoost has
Draw();

when I attempt to run through a list of objects and call:

objects[loop1].Draw();

the SpeedBoost::Draw() is never called
only the MObject::Draw() is called.

I need it to call the implementation of the Draw for the class that it is not the base class draw.

I'm know that implementing a linked list would probably work but that's added complexity for something that an array should hopefully be able to do.

Share this post


Link to post
Share on other sites
Advertisement
*(object+obj_counter)= SpeedBoost(args...);


You are slicing your SpeedBoost here. The temporary SpeedBoost you create here is truncated to a MObject so it can fit inside the MObject array. Try the following code:


// Create
MObject** objects = new MObject*[num_of_obj];

// Use
objects[0] = new SpeedBoost( ... );
objects[1] = new OtherObject( ... );

// Cleanup
for ( ... )
delete objects[idx];
delete[] objects;

Share this post


Link to post
Share on other sites
Ok that worked perfectly, and I understand now what slicing is but I don't quite understand why the solution works.

lets see if I can figure it out. MObject** is a pointer to an array of pointers so it's allocates a slot to each pointer but doesn't allocate them a type yet? so now that they have not be allocated a type we can use new to allocate them to the correct class?

Share this post


Link to post
Share on other sites
MObject** is a pointer to an array of pointers so it's allocates a slot to each pointer but doesn't allocate them a type yet? so now that they have not be allocated a type we can use new to allocate them to the correct class?


Yes. Keep in mind that MObject is an MObject itself, while a MObject* (or MOjbect&) is the MObject interface of an MObject or one of its derived types.

Share this post


Link to post
Share on other sites
I may be wrong - you need to specify that SpeedBoost is also a virtual function. Thats why its never called Edited by dimitri.adamou

Share this post


Link to post
Share on other sites

I may be wrong - you need to specify that SpeedBoost is also a virtual function. Thats why its never called

I could be wrong too but alternatively if there's no Mobject draw() method as such he could make it pure virtual by appending =0

Share this post


Link to post
Share on other sites
A slightly more idiomatic C++ solution:

class Object
{
public:
virtual void Display() const = 0;
};

class IntObject : public Object
{
public:
explicit IntObject(int value)
: MyValue(value)
{ }

virtual void Display() const
{
std::cout << "Integer object: " << MyValue << std::endl;
}

private:
int MyValue;
};

class StringObject : public Object
{
public:
explicit StringObject(const std::string& value)
: MyValue(value)
{ }

virtual void Display() const
{
std::cout << "String object: " << MyValue << std::endl;
}

private:
std::string MyValue;
};

int main()
{
// Also try boost::shared_ptr or boost::scoped_ptr if you're on an outdated compiler
typedef std::vector<std::unique_ptr<Object>> ObjectContainer;
ObjectContainer objects;

// Create us some objects!
objects.push_back(new IntObject(1));
objects.push_back(new StringObject("test"));

// Do stuff the C++11 way
std::for_each(
std::begin(objects),
std::end(objects),
[](const std::unique_ptr<Object>& obj)
{
obj->Display();
}
);

// Alternately, the C++98 way
for(ObjectContainer::const_iterator iter = objects.begin(), end = objects.end(); iter != end; ++iter)
{
(*iter)->Display();
}

// Note: no need to explicitly delete anything!
}



My C++11 is still getting into shape, so feel free to nitpick on that bit :-) Also, please feel free to ask any questions this code might raise!


(Note also that this could be done with templates instead of manually creating an IntObject and StringObject, but that seems a bit excessive in the context of the OP's question.) Edited by ApochPiQ
Accidentally a void.

Share this post


Link to post
Share on other sites

// Do stuff the C++11 way
std::for_each(
std::begin(objects),
std::end(objects),
[](const std::unique_ptr& obj)
{
obj->Display();
}
);

I can't help but feel it's clearer to write it this way (still C++11).

for (const auto& obj: objects)
{
obj->Display();
}

Share this post


Link to post
Share on other sites
Yeah, ranged for is also an option. I can't remember how widespread compiler support is, though, so I usually don't think of it offhand.

Share this post


Link to post
Share on other sites
ApochPiQ:

I think you meant


objects.push_back(std::unique_ptr<Object>(new IntObject(1)));
objects.push_back(std::unique_ptr<Object>(new StringObject("Test")));


Or maybe not, if your compiler doesn't force you to be so verbose. VS10 does.

Also you forgot to give Object a virtual dtor.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!