Приведение производного класса к базовому классу

У меня есть небольшая хитрая проблема, с которой я столкнулся. Я считаю, что проблема связана с тем, как я кастую вещи.

Итак, у меня есть базовый класс под названием combatEntity, Имеет следующую функцию

class combatEntity {
public:
virtual void update();
};

У меня тогда есть классный моб, который является производным от combatEntity, переопределяет функцию обновления:

class mob : public combatEntity {
public:
virtual void update();

}

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

class monster: public mob {
public:
virtual void update();
}

У меня есть указатель fightEntity под названием i:

combatEntity* i;

Тогда у меня есть:

//returns a mob* pointer (needs explicit cast)
monster* newMonster = getMob();
i = newMonster;

getMob() функция:

mob* getMob() {
mob* newMob = new mob();
//set some data in newMob
return newMob;
}

Когда я звоню i->update()это вызывает mob::update(), так как newMonster установлен на «новый моб ();», так как getMob() возвращает указатель нового моба. Когда я звоню i->update()Мне нужно это позвонить monster::update(), но используя точки останова, я вижу, что это вызывает mob::update() и не monster::update(),

поэтому мне нужно создать новый monster объект, но все еще имеют данные базового класса, заполненные объектом, возвращаемым из getMob(), но функции должны быть переопределены правильно. Я также пробовал dynamic_cast, static_cast и reinterpret_cast, и, похоже, ни один из них не работает. Или мне нужно привести свой базовый класс к производному классу, при этом должным образом переопределяя функции с производным классом.

Надеюсь, это имеет смысл. Любой совет будет принят во внимание.

0

Решение

взгляните на свое иерархическое дерево, убедитесь, что классы связаны так, как вы думаете.

Этот код

#include <iostream>

struct combatEntity
{
virtual void Update() { std::cout << "Combat Entity\n"; };
};

struct mob : combatEntity
{
virtual void Update() { std::cout << "Mob\n"; };
};

struct monster : mob
{
virtual void Update() { std::cout << "Monster\n"; };
};

int main(int argc, char **argv)
{
combatEntity *ce = new monster;
ce->Update();
delete ce;

return 0;
}

создает этот вывод:

Monster

Источник: http://ideone.com/k6LAB

2

Другие решения

Ваша линия

monster* newMonster = getMob();

не должен компилироваться. я получил

error: invalid conversion from ‘mob*’ to ‘monster*’ [-fpermissive]

(также ваша линия i = monster; следует предположительно прочитать i = newMonster;). Это все объясняет, я думаю (см. Также комментарий от Лучиана).

0

Ну, так как вы используете виртуальный, «update» всегда будет вызывать правильную функцию, независимо от того, какой вы объявите указатель. Вот как работает «виртуальный».

Если вы хотите, чтобы ваши указатели определяли вызываемый объект, а не сам объект, сделайте материал не виртуальным. В этом случае тип указателя будет определять, какое «обновление» вызывается.

Если вы хотите и то и другое, вы все равно можете вызвать что-то вроде monster :: update (), а не просто обновить. Однако, если вы не делаете это изнутри функции обновления производного класса (чтобы вызвать реализацию суперкласса), попытка обойти иерархию наследования может быть признаком плохого дизайна.

0