Jump to content

  • Log In with Google      Sign In   
  • Create Account

Polymorphism and pointer arrays in c++


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 Vero   Members   -  Reputation: 138

Like
0Likes
Like

Posted 26 July 2012 - 02:15 PM

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.

Sponsor:

#2 fastcall22   Crossbones+   -  Reputation: 4477

Like
4Likes
Like

Posted 26 July 2012 - 02:31 PM

*(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;

c3RhdGljIGNoYXIgeW91cl9tb21bMVVMTCA8PCA2NF07CnNwcmludGYoeW91cl9tb20sICJpcyBmYXQiKTs=

#3 Vero   Members   -  Reputation: 138

Like
0Likes
Like

Posted 26 July 2012 - 02:49 PM

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?

#4 fastcall22   Crossbones+   -  Reputation: 4477

Like
1Likes
Like

Posted 26 July 2012 - 03:41 PM

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.
c3RhdGljIGNoYXIgeW91cl9tb21bMVVMTCA8PCA2NF07CnNwcmludGYoeW91cl9tb20sICJpcyBmYXQiKTs=

#5 dimitri.adamou   Members   -  Reputation: 329

Like
0Likes
Like

Posted 26 July 2012 - 04:11 PM

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

Edited by dimitri.adamou, 26 July 2012 - 04:13 PM.


#6 Fredericvo   Members   -  Reputation: 487

Like
0Likes
Like

Posted 26 July 2012 - 07:32 PM

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


#7 ApochPiQ   Moderators   -  Reputation: 16419

Like
3Likes
Like

Posted 26 July 2012 - 07:59 PM

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, 26 July 2012 - 08:00 PM.
Accidentally a void.


#8 Bregma   Crossbones+   -  Reputation: 5503

Like
0Likes
Like

Posted 26 July 2012 - 09:14 PM

// 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();
}

Stephen M. Webb
Professional Free Software Developer

#9 ApochPiQ   Moderators   -  Reputation: 16419

Like
0Likes
Like

Posted 26 July 2012 - 10:17 PM

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.

#10 Amnesty2   Members   -  Reputation: 203

Like
0Likes
Like

Posted 27 July 2012 - 11:22 PM

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.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS