Виртуальные функции: итерация по вектору, заполненному объектами подкласса
Краткое Описание:
Я перебираю вектор, вызывающий виртуальную функцию для каждого объекта в векторе, чтобы выполнить последовательность действий. Вектор имеет базовый класс, как и итератор. Все объекты-дети. Когда виртуальная функция вызывается, она выполняет функцию базового класса.
(Действительно) Полное Описание: Я пытаюсь смоделировать существо, которое имеет набор поведений. Мой базовый класс является абстрактным только с двумя функциями (virtual) который все подклассы переопределили:
class Behavior
{
public:
Behavior();
~Behavior(void){}
virtual void execute(){}
virtual BEHAVIOR_TYPE getType() {return m_Type;}
protected:
BEHAVIOR_TYPE m_Type;
};
Я создал несколько видов поведения детей, таких как перемещение, потребление, разведчик и т. д.
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;
};
Я создал вектор, на который я толкнул экземпляры каждого подкласса поведения, а также итератор, чтобы пересечь его:
vector<Behavior> m_Behavior;
vector<Behavior>::iterator bIt;
когда существо получает последовательность действий, я пытаюсь перебрать вектор, разыменовать итератор и вызвать функцию execute:
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();
}
}
проблема что он выполняет функцию родителя, а не функцию ребенка.
в моем понимании поздней привязки он должен автоматически вызывать соответствующую функцию на основе типа объекта, который вызывал его, а не типа указателя, с которым он был вызван, и в моем коде я ожидал, что он будет указывать на дочерний объект.
очевидно, я сделал ошибку и как-то сказал программе, что я хочу, чтобы они рассматривались как родители, а не детей, но я не могу найти свою ошибку.
любая помощь была бы весьма признательна.
2 ответов
класс vector<Behavior>
делает копии всего, что вы храните внутри него, используя конструктор копирования Behavior::Behavior(const Behavior&);
. Это разрушает полиморфизм. Вместо этого вам нужно использовать указатель или смарт-указатель в контейнере:
vector<Behavior*> m_Behavior; // I will take care of new and delete
vector<shared_ptr<Behavior> > m_Behavior; // easier
если у вас нет std::shared_ptr
или std::tr1::shared_ptr
на #include <memory>
или аналогичный, возможно, вы можете использовать Boost.
добавляется экземпляров классов вектору. Это приводит к для нарезки.
что вам нужно сделать, это добавить указатели к экземплярам поведения и измените цикл, чтобы сделать
(*myBehavior)->execute();