[C++ problem] Vector pointers to pointer of inherited class?

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Raden Mu'az
Posts: 12
Joined: Sat Dec 27, 2008 1:26 pm
Contact:

[C++ problem] Vector pointers to pointer of inherited class?

Post by Raden Mu'az »

Hi. I'm a newbie in Irrlicht. Been programming in Python and badly spoiled with its automatic pointers management and class ducktyping, etc,etc - So I become really sucks at C++ pointers stuff.

I had a problem managing object pointers in a vector pointer for keeping track of objects and accessing their functions in C++.

I made an Actor class which is the base class for other object

Code: Select all

class Actor 
{
};
Then I made a Spaceship class, which is derived from Actor class
The Spaceship class has shoot() function

Code: Select all

class Spaceship : public Actor
{
public:
  void shoot()
  {
  }
};
Then I made a vector to keep the the Actor collections.

Code: Select all

vector<Actor*>*collections;

Spaceship* s = new Spaceship;
collections->push_back(s);
But when I do this, I'll get nasty error saying that "Actor class has no function shoot()", which the Actor is actually the Spaceship, and the Spacehsip actually a class is derived from Actor class. :?

Code: Select all

(*collections)[0]->shoot();
Can anyone help me on this?
Sylence
Posts: 725
Joined: Sat Mar 03, 2007 9:01 pm
Location: Germany
Contact:

Post by Sylence »

You need to cast the object to Actor:

Code: Select all

((Spaceship*)(*collections)[0])->shoot();
Or something like this... why do you use a pointer for the array ?

Code: Select all

vector<Actor*> collections;
This will work as well and you can use the vector more easy:

Code: Select all

((Spacehip*)colletions[0])->shoot();
Software documentation is like sex. If it's good you want more. If it's bad it's better than nothing.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

If all Actor types are expected to be able to shoot, you could make shoot() a virtual function in the base class. Otherwise, you could just make an array of spaceships...

Code: Select all

std::vector<Spaceship*> spaceships;
If you add another derived Actor you would just put them into their own array.

If you have a heterogeneous collection (a collection that contains objects of different types), and you only have a base class pointer, you'll have to have some system for identifying the actual type of the objects so that you know what you can cast them to.

Travis
Raden Mu'az
Posts: 12
Joined: Sat Dec 27, 2008 1:26 pm
Contact:

Post by Raden Mu'az »

Thanks a lot! :D.
Casting works, however, changing class methods to 'virtual' is much better for me.

Anyway:
vitek wrote: If you have a heterogeneous collection (a collection that contains objects of different types), and you only have a base class pointer, you'll have to have some system for identifying the actual type of the objects so that you know what you can cast them to.
Travis
How do I detect class types in C++?
Dark_Kilauea
Posts: 368
Joined: Tue Aug 21, 2007 1:43 am
Location: The Middle of Nowhere

Post by Dark_Kilauea »

In my experience, I've used a small unsigned char type member in my base class which contains a value in an enum relating to what derived class it actually is.

For example:

Code: Select all

enum ClassTypes
{
    ECT_DERIVED,
    ECT_DERIVED2,
    ...
    ECT_COUNT
};

class Base
{
    unsigned char Type;
};

class Derived : public Base
{
    Derived() { Type = ECT_DERIVED; }
};

class Derived2 : public Base
{
    Derived2() { Type = ECT_DERIVED2; }
};
You should get the point by now ;)
rogerborg wrote:Every time someone learns to use a debugger, an angel gets their wings.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

That is one way to do it. It qould be a bit safer if you made Type const in the base class, added an accessor, and added a protected Base constructor that took a ClassType (or an unsigned int) and used that to initialize the Type member. Changing the member to an unsigned int is often better for performance and minimizing memory waste due to padding.

Another way is to add a pure virtual method in the base class and overriding the virtual in the derived classes. The advantage here is that you don't need to store the type id in every object instance, which can save memory at the cost of a virtual function call.

Travis
Post Reply