Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
245 views
in Technique[技术] by (71.8m points)

c++ - Virtual Functions: Iterating over a vector<Base Class> that is populated with subclass objects

Short Description:
I am iterating over a vector calling a virtual function on every object in the vector in order to execute a sequence of actions. The vector is of the base class as is the iterator. All the objects are children. When the virtual function is called it executes the base class's function.

(Really) Long Description: I am attempting to model a creature that has a set of behaviors. My base class is abstract with only two functions (virtual) which all the subclasses have overridden:

class Behavior
{
public:
     Behavior();
    ~Behavior(void){}
 virtual void execute(){} 
 virtual BEHAVIOR_TYPE getType() {return m_Type;}


protected:
BEHAVIOR_TYPE m_Type;
};

I have created a number of children behaviors, such as move, consume, scout, etc.

class Move :
    public Behavior
{
public:
BEHAVIOR_TYPE getType() {return m_Type;}
    enum Direction {N, NE, E, SE, S, SW, W, NW};
Move(DOCO * d);
~Move(void);
void execute() ;
    Direction chooseDirection();
    void setDirection(Direction newDirection);
private:
    Direction m_Direction;
    DOCO *I;
BEHAVIOR_TYPE m_Type;

};

I created a vector onto which I pushed instances of each Behavior subclass as well as an iterator to traverse it:

vector<Behavior> m_Behavior;
vector<Behavior>::iterator bIt;

When the creature gets an action sequence, I try to iterate over the vector, dereference the iterator, and call the execute function:

void World::justDoIt()
{
    for(dIt=myDOCO.begin(); dIt!=myDOCO.end(); ++dIt)
{
    vector<Behavior>::iterator myBehavior=(dIt)->getFirstBehavior();
    vector<Behavior>::iterator end=(dIt)->getLastBehavior();
    for(myBehavior; myBehavior!=end; ++myBehavior)

        (*myBehavior).execute();
}
}

The problem is that it executes the parent's function rather than the child's function.

In my understanding of late binding it should automatically call the appropriate function based on the type of object that was calling it rather than the type of pointer with which it was called, and in my code I anticipated it would be pointing to the child object.

Obviously I have made an error and somehow told the program that I want these to be treated as parents instead of children, but I cannot find my error.

A second symptom is that it will not let me make the parents function pure virtual, because it says it cannot instantiate an abstract class. I am not instantiating it explicitly anywhere in my code, but there must be somewhere I am doing it implicitly. I cannot find where, however. Certainly creating a vector to hold objects of the parent class does not require instantiating the parent, and that is the only time I reference the parent class directly.

Any help would be greatly appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The class vector<Behavior> makes copies of whatever you store inside it, using the copy constructor Behavior::Behavior(const Behavior&);. This destroys the polymorphism. You need to use a pointer or smart pointer in the container instead:

vector<Behavior*> m_Behavior; // I will take care of new and delete
vector<shared_ptr<Behavior> > m_Behavior; // easier

If you don't have std::shared_ptr or std::tr1::shared_ptr in #include <memory> or similar, maybe you can use Boost's.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...