samedi 30 mai 2015

Calling parent methods and accessing it's protected fields

Me and my friends are trying to write some kind of a game as a study project in university. We use Eclipse and write program on C++11. And we met very strange (as for me) problem.

We have special class PlayingObject:

    class PlayingObject{
    protected:
        Action* currAction;
        std::queue<Action*> ActionQueue;
        .....
    public:
        virtual Action* GetAction();
        virtual void NextAction();
        virtual void AddAction(Action* action, bool replace);
        virtual Stop();
        .....
    }

This class has two children, Unit and Building. They both override methods, mentioned before, but not all. Unit:

   class Unit: public PlayingObject{
   public:
       .....
       virtual Action* GetAction();
       virtual void NextAction();
       virtual void AddAction(Action* action, bool replace);
       virtual Stop();
       .....
   }

and the same thing in Building:

   class Building: public PlayingObject{
   public:
       .....
       virtual Action* GetAction();
       virtual void NextAction();
       virtual void AddAction(Action* action, bool replace);
       virtual Stop();
       .....
       void Produce();
   }

Unit::AddAction() works OK. We can even use such a code:

   Unit* unit=new Unit(...);
   unit->Stop();

Stop() is not overriden in Unit, but it works. Unit has access to currAction and ActionQueue.

But problem occures when we make same things in Building. We cannot call parent methods in Building;

   Building* building=new Building(...);
   building->Stop(); //crashes program
   building->NextAction(); //crashes program
   unsigned int temp=building->ActionQueue.size(); //suddenly returns very large number, when it should not
   Action* act=ActionQueue.front(); //crashes program

The idea is that project builds well. It works (I mean, we control units, they move and can be picked) until we call building->NextAction() or building->AddAction(action, true). Project closes without any log.

It happens exactly when we write realisation of Building::Produce():

   void Building::Produce(){
       .....
       this->AddAction(action, true); //here it crashes
       //AddAction(action, true); //also would crash
       PlayingObject::AddAction(actioon, true); //no crash, but works incorrectly; ActionQueue.size() inside PlayingObject::AddAction() returns 18446744073709551552 and it doesn't look real;
       this->ActionQueue.size(); //also returns this number
       Action* act;
       act=ActionQueue.front(); //crashes project. again.
   }

We almost sure we don't push something bad into ActionQueue, we checked it many times. And when we try to override this methods like this:

   void Building::AddAction(Action* action, bool replace){
       PlayingObject::AddAction(action, replace);
   }

and then call building->AddAction(...) in Building::Produce(), it also crashes, like before.

We cannot understand, what happens here. There is, in fact, no difference between Building and Unit. Building is even simplier. But why we cannot call Building::AddAction() from other Building methods even if it's overriden?!

Please, help me to understand, what it is and why one child can override parant's methods and has access to it's protected members, and another can do nothing of this correctly.

Aucun commentaire:

Enregistrer un commentaire