1

I've read a lot of things on the virtual functions, but I'm still not able to get something to work how I want.

Basically, I've got the following class:

class Body
{

    protected:
        scene::ISceneNode* Model;
        virtual void setModel();
    public:
        Body( core::vector3df Position, core::vector3df Rotation );
};


Body::Body( core::vector3df Position, core::vector3df Rotation )
{
    CurrentThrust = 0;
    setModel();
    Model->setPosition( Position );
    Model->setRotation( Rotation );
}

void Body::setModel()
{
    Model = Engine::Instance->GetSceneManager()->addCubeSceneNode();
    Model->setMaterialFlag( video::EMF_LIGHTING, false );
}

I am create new classes inheriting Body, and the idea is that I override "setModel()" in those classes, and the constructor will load my new model, instead of the default; like below

class Craft : public Body
{
    protected:
        virtual void setModel();
    public:
        Craft( core::vector3df Position, core::vector3df Rotation );
};

Craft::Craft( core::vector3df Position, core::vector3df Rotation ) : Body(Position, Rotation)
{
    // Other stuff
}

void Craft::setModel()
{
    Model = Engine::Instance->GetSceneManager()->addAnimatedMeshSceneNode( Engine::Instance->GetSceneManager()->getMesh("resource/X-17 Viper flying.obj") );  // addCubeSceneNode();
    Model->setMaterialFlag( video::EMF_LIGHTING, false );
    Model->setScale( core::vector3df(0.1f) );
}

However, it always creates a Cube model instead of my Viper mode when I create a new instance of Craft.

Is it possible to get virtual functions to work like I'm thinking? or do I need to just change my constructors to create the models in their respective classes?

Thanks

Marq Watkin
  • 140
  • 1
  • 1
  • 6

3 Answers3

3

Is it possible to get virtual functions to work like I'm thinking?

No. When you call one from a constructor, it's dispatched according to the class being initialised (Body in this case), not the final overrider (since that hasn't been initialised yet, so can't be accessed safely).

or do I need to just change my constructors to create the models in their respective classes?

That's probably the simplest solution. I'd suggest passing the model as a constructor argument to Body. That way, it's impossible to forget to set it.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1
class Craft : public Body
{
    protected:
        void setModel();
    public:
        Craft( core::vector3df Position, core::vector3df Rotation );
};

Don't use the keyword virtual in the Class Craft.

Banukobhan Nagendram
  • 2,335
  • 3
  • 22
  • 27
  • 1
    `virtual` is valid. `override` is better if supported. And it is unrelated to OP problem anyway. – Jarod42 Feb 14 '14 at 16:16
0

Like mathematician1975 pointed out, you should never use a virtual method inside a constructor or a destructor.

An object being built by a constructor cannot be considered of the constructor's class until the control flow leaves the constructor. Whenever you will call a virtual method inside of Craft's constructor, you will always end up invoking a Body's method.

Since setting your models means loading a mesh from a file, which is usually a quite expensive operation, I suggest that you do not do it until you really need it, i.e. whenever your model is requested. At this point, your virtual should behave like you expect it to.