2014-12-21 4 views
-1

Я потратил несколько часов на то, чтобы найти эту ошибку, теперь, по крайней мере, я знаю, где проблема, но я понятия не имею, почему.Полиморфизм не работает так, как должно было

Так у меня есть:

std::vector< std::vector <Organism* > >world; 

У меня есть базовый класс Organism и дочерние классы Beetle и Ant.

В базовом классе Organism У меня есть виртуальные функции:

private: 
     bool energy; 
    public: 
    Organism():energy(true){} 
    virtual void removeEnergy(){ 
     energy = false; 
    } 
    virtual bool hasEnergy(){ 
     return energy; 
    } 

    virtual void resetEnergy(){ 
     energy = true; 
    } 

И я НЕ переписаны их ни в одном из дочерних классов. Я назвал конструктор базового класса в дочерних классах.

Когда я называю эту функцию:

void World::replaceOrganism(int x, int y, int newX, int newY){ 
     world[newX][newY] = world[x][y]; 
     world[x][y] = new Organism; 
     world[newX][newY]->removeEnergy(); // this line 
} 

Он удаляет энергию только из этого класса объектов. Это означает, что если в векторе world является несколькими Жуков, то с помощью этой линии:

world[newX][newY]->removeEnergy(); 

энергии удаляется из всех из них.

Я думаю, что-то с векторами. У кого-нибудь есть предложения? Если вам нужно больше информации -> комментарий, я добавлю. более

Одно дело, если я удалить эту строку:

world[newX][newY]->removeEnergy(); 

тогда энергия Organism объектов класса или его детей не меняется.

EDITED

Создание мирового вектора:

world.resize(worldSizeX); 

    for (int x = 0; x < worldSizeX; x++){ 
     world[x] = std::vector< Organism* >(worldSizeY); 

     // INITATES world ARRAY 
     for (int y = 0; y < worldSizeY; y++){ 
      world[x][y] = new Organism; 
     } 
     // !INITATES world ARRAY 
    } 

EDITED

Изменение функции replaceOrganism с этим:

void World::replaceOrganism(int x, int y, int newX, int newY){ 
     delete world[newX][newY]; 
     world[newX][newY] = world[x][y]; 
     delete world[x][y]; 
     world[x][y] = new Organism; 
} 

удаляет все объекты класса, которое указывает слово [newX] [newY], но функция вызывается только один раз.

EDITED

функция, которая заменяет Organism объекты класса со своими детьми.

bool World::createOrganism(int x, int y, Organism* organism){ 
    Organism* empty = new Organism; 
    if (world[x][y]->type() != empty->type()){ 
     delete empty; 
     return false; 
    } 
    else{ 
     delete empty; 
     world[x][y] = organism; 
     return true; 
    } 
} 

Я называю его:

createOrganism(2,3,new Beetle); 

EDITED

void World::generateOrganisms(Organism* organism, int amount){ 
    while (amount != 0){ 
     int x = rand() % worldSizeX; 
     int y = rand() % worldSizeY; 
     if (createOrganism(x, y, organism)){ 
      amount--; 
     } 
    } 
} 

Все указывает на тот же объект.

+0

Проблемы с разделением? –

+6

Это непонятно. Что вы подразумеваете под «удаляется из всех». Пожалуйста, создайте тестовый пример, демонстрирующий это. –

+0

Вы уверены, что вы правильно инициализируете мир? Как я могу догадаться, это означает, что каждый указатель Beetle в вашем мире указывает на того же Beetle. – Alexandru

ответ

3

В generateOrganisms(Organism* organism, int amount) все указатели, которые вы указали, относятся к одному и тому же организму. Так все-таки жук.

Вам необходимо предусмотреть дополнительную виртуальную функцию для Организма:

Organism *clone() { 
    // create a new organism of the same type 
    } 

Этой виртуальная функция должна быть перезаписана для каждого ребенка, чтобы создать новый организм, используя правильный конструктор.

Затем можно обновить функцию создания:

bool World::createOrganism(int x, int y, Organism* organism){ 
    Organism* empty = new Organism; 
    if (world[x][y]->type() != empty->type()){ 
     delete empty; 
     return false; 
    } 
    else{ 
     delete empty; 
     world[x][y] = organism->clone(); // use a clone, not the original 
     return true; 
    } 
} 

Кроме того, я не уверен, что все неиспользуемые объекты будут удалены по мере необходимости (по крайней мере, трудно сказать только snipets вы предоставляете). Возможно, стоит исследовать потенциальное использование shared_ptr, чтобы избежать утечки памяти.

+0

Итак, вы говорите, если я вызываю функции типа 'myFunction (новый класс);' . Тогда объект 'new Class' никогда не удаляется? – Cirvis

+0

Thats it! 'new' создает объект, который останется до тех пор, пока вы его не удалите. Это отличается от анонимного объекта, который автоматически распаковывается в конце выражения или из локального объекта, который уничтожается в конце блока/функции, в которой он был создан. – Christophe

+0

Я только что прочитал, что он отличается от компилятора компилятором. И это не кажется хорошей практикой. И писать в каждой функции 'if (string ==" Beetle ") { // делать вещи }' тоже не кажется хорошим. Что ты предлагаешь? – Cirvis

Смежные вопросы