static_cast<some_type*>(map::at())->some_metod() don't work

Get answers to all your basic programming questions. No Ogre questions, please!
User avatar
Melnik
Gnoblar
Posts: 10
Joined: Wed Jul 11, 2012 8:46 pm
Location: Ukraine

static_cast<some_type*>(map::at())->some_metod() don't work

Post by Melnik »

Hi all!
I have problem with static_casting of std::map:

Code: Select all

Orse::GameObject* copt = Orse::Root::getSingletonPtr()->getWorld("mainW")->getGameObject("Copter");
static_cast<Copter*>(copt)->applyForce(0.70f);
method getGameObject() return GameObject*
when casting copt to Copter* i get exception:

Code: Select all

terminate called after throwing an instance of 'std::out_of_range'
  what():  map::at
Aborted
UPD: when i don't use static_cast and call same method of GameObject i don't get exception.
Why, and how to fix?
Last edited by Melnik on Wed Oct 17, 2012 6:01 pm, edited 2 times in total.
bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia
x 201

Re: static_cast<some_type*>(map::at())->some_metod() don't w

Post by bstone »

That has nothing to do with static_cast<>. You're just asking for something that isn't in the map, hence std::out_of_range.
User avatar
Melnik
Gnoblar
Posts: 10
Joined: Wed Jul 11, 2012 8:46 pm
Location: Ukraine

Re: static_cast<some_type*>(map::at())->some_metod() don't w

Post by Melnik »

bstone wrote:That has nothing to do with static_cast<>. You're just asking for something that isn't in the map, hence std::out_of_range.
But when i don't use static_cast and call same method of GameObject i don't get exception.
bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia
x 201

Re: static_cast<some_type*>(map::at())->some_metod() don't w

Post by bstone »

Does that mean that

Code: Select all

Orse::GameObject* copt = Orse::Root::getSingletonPtr()->getWorld("mainW")->getGameObject("Copter");
copt->applyForce(0.70f);
doesn't raise the exception?
User avatar
Melnik
Gnoblar
Posts: 10
Joined: Wed Jul 11, 2012 8:46 pm
Location: Ukraine

Re: static_cast<some_type*>(map::at())->some_metod() don't w

Post by Melnik »

bstone wrote:Does that mean that

Code: Select all

Orse::GameObject* copt = Orse::Root::getSingletonPtr()->getWorld("mainW")->getGameObject("Copter");
copt->applyForce(0.70f);
doesn't raise the exception?
This means that without casting I get GameObject object by method getGameObject (of course I can't then call the method applyForce because c++ does not allow) but I want to call the method applyForce.
applyForce() is method of Copter class.
bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia
x 201

Re: static_cast<some_type*>(map::at())->some_metod() don't w

Post by bstone »

Yep, so when you call that method you get that exception. That can happen for two reasons: a) GameObject::applyForce() accesses some map and "gets out of bounds" as I told you before; b) Your copt is actually not an instance of Copt and you fire some random code into the wild which ends up accessing some map and "gets out of bounds".
bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia
x 201

Re: static_cast<some_type*>(map::at())->some_metod() don't w

Post by bstone »

In other words saying that without static_cast<> it does work is far from the truth.
User avatar
syedhs
Silver Sponsor
Silver Sponsor
Posts: 2703
Joined: Mon Aug 29, 2005 3:24 pm
Location: Kuala Lumpur, Malaysia
x 51

Re: static_cast<some_type*>(map::at())->some_metod() don't w

Post by syedhs »

It will be easier if you can just do some debugging and find out more details ie if the error is actually coming out from your function (not stl)
A willow deeply scarred, somebody's broken heart
And a washed-out dream
They follow the pattern of the wind, ya' see
Cause they got no place to be
That's why I'm starting with me
User avatar
Melnik
Gnoblar
Posts: 10
Joined: Wed Jul 11, 2012 8:46 pm
Location: Ukraine

Re: static_cast<some_type*>(map::at())->some_metod() don't w

Post by Melnik »

This is GameObject class:

Code: Select all

namespace Orse {
  
  class World;

class GameObject {
  public:
    virtual ~GameObject() {}
    virtual void init() = 0;
    virtual Ogre::SceneNode* getSceneNode() const = 0;
    virtual void onCollide(Orse::Collision* collision) = 0;
    string getName() {return m_Name;}
    void setName(string name) {m_Name = name;}
    uint getId() {return m_Id;}
    void setId(uint id) {m_Id = id;}
  private:
    string m_Name;
    uint m_Id;
};

}//end namespace
Copter class:

Code: Select all

class Copter : public Orse::GameObject {
  public:
    Copter();
    virtual ~Copter();
    
    virtual void init();
    virtual Ogre::SceneNode* getSceneNode() const {return m_Node;}
    virtual void onCollide( Orse::Collision* collision );
    
    void applyStaticForce(float force) {m_StaticForce += force;}
    void applyForce(float force);
    void applyForce(uint nMotor, float force);
  private:
    Ogre::SceneNode* m_Node;
    float m_StaticForce;
};
I need to call the method applyForce
I try this way:

Code: Select all

Orse::GameObject* copt = Orse::Root::getSingletonPtr()->getWorld("mainW")->getGameObject("Copter");
static_cast<Copter*>(copt)->applyForce(0.70f);
But i get exception
Maybe I'm wrong designed it
User avatar
syedhs
Silver Sponsor
Silver Sponsor
Posts: 2703
Joined: Mon Aug 29, 2005 3:24 pm
Location: Kuala Lumpur, Malaysia
x 51

Re: static_cast<some_type*>(map::at())->some_metod() don't w

Post by syedhs »

I think what bstone has said previously is correct, what is the code for applyForce anyway? :mrgreen: And if you cannot reveal the source code, place breakpoint inside applyForce, and see if the code manages to reach there before throwing exception - this what I would do if I were you.

Btw, on the design issue you can just make things more flexible by doing this:-

Code: Select all

class GameObject {
...
..
virtual void setProperty(const String& key, const String& value)=0;
};

class Copter : public GameObject {

virtual void setProperty(const String& key, const String& value) {
  if (key == "apply_force")
      applyForce(StringConverter::parseReal(value));
}
That way, you do not have to detect (and then cast) which class an object belongs to, as you only need to execute setProperty which is available for all classes derived from GameObject.
A willow deeply scarred, somebody's broken heart
And a washed-out dream
They follow the pattern of the wind, ya' see
Cause they got no place to be
That's why I'm starting with me
Valentin Perrelle
Halfling
Posts: 54
Joined: Thu Sep 15, 2011 4:14 pm
x 2

Re: static_cast<some_type*>(map::at())->some_metod() don't w

Post by Valentin Perrelle »

And if it is not a copter you set a property which has no meaning without raising any exception thus making the bug even harder to find.

When you can't be sure that the object you cast is of the type you expect, use dynamic_cast instead of static_cast and test the return of the dynamic_cast : if it is 0, then the cast is invalid. It is important for your case. Since your objects are identified by strings which can be set dynamically, you have no reason that the object you retrieve is statically of the right type. If it's unhandy to dynamic cast and check each time, you can change getGameObject to template it with the expected type of the object returned. You can then do the dynamic_cast in this method and raise an exception whenver the cast returns 0.
User avatar
Melnik
Gnoblar
Posts: 10
Joined: Wed Jul 11, 2012 8:46 pm
Location: Ukraine

Re: static_cast<some_type*>(map::at())->some_metod() don't w

Post by Melnik »

SOLVED :D
Exception caused due to an segmentation error in applyForce.
I do not know why so, but when I comment implementation, I waren't got more errors :D