Проблема с наследованием C++, среда Borland Builder 6.0

239
15 декабря 2016, 16:16

Есть такая проблема: имеется иерархия классов. В производных появляются новые методы. Есть массив указателей на базовый класс. Когда я создаю экземпляр производного класса и обращаюсь к нему через указатель базового, он пытается найти метод в базовом классе, который не существует.
Люди добрые, помогите, пожалуйста. Я пытался делать понижающее преобразование типа указателя с помощью dynamic_cast:

MO[0] = dynamic_cast<hero*>(MO[0]);

Указатель вроде как меняет тип, но компилятор всё равно орёт

"[C++ Error] Main.cpp(230): E2316 'Move' is not a member of 'map_object'".

Вот важная часть кода:

class map_object {
    int x,y, index;
  public:
    virtual void Draw()=0;
    void set_x(int _x);
    void set_y(int _y);
    int get_x();
    int get_y()y;
    void set_index();
    int get_index();
    map_object(int _x, int _y);
};
map_object *MO[100];
class moving_object: public map_object {
  public:
    virtual void Move(int _d);
    moving_object(int _x, int _y):map_object(_x, _y);
};
class creature: public moving_object {
    int health;
    void Death();
  public:
    void cure(int _health);
    void damage(int _damage);
    int get_health();
    creature(int _x, int _y, int _health):moving_object(_x, _y);
};
class mage: public creature {
    int mana;
  public:
    void mana_fill(int _mana);
    void mana_reduce(int _mana);
    int get_mana();
    mage(int _x, int _y, int _health, int _mana):creature(_x, _y, _health);
};
class hero: public mage {
  public:
    void Draw();
    hero(int _x, int _y, int _health, int _mana):mage(_x, _y, _health, _mana);
};
void __fastcall TfrmMain::FormKeyPress(TObject *Sender, char &Key) {
  switch (Key) {
    case 'w': {MO[0]->Move(0); break;}
    case 'd': {MO[0]->Move(1); break;}
    case 's': {MO[0]->Move(2); break;}
    case 'a': {MO[0]->Move(3); break;}
  }
}
Answer 1

Попробуйте посмотреть на ваш код глазами компилятора. Вы объявили MO как массив указателей на объекты класса map_object, в котором метода Move нет. Вы присвоили его элементам значения через dynamic_cast к hero - наследнику map_object. Чего вы этим добились? А ничего. MO как был массивом указателей на map_object, так им и остался. Компилятору, в общем-то, всё равно, каких наследников map_object'а вы присваиваете MO, при обращении по этому указателю он всегда будет видеть только те поля и методы, которые объявлены в map_object. Если вы хотите вызывать методы наследников по указателю на их предка, необходимо привести указатель на предка к указателю на наследника. Именно здесь и нужно* использовать понижающее преобразование:

dynamic_cast<hero*>(MO[0])->Move(0);

* На самом деле не нужно. Если ваша иерархия классов подразумевает принудительные понижающие преобразования, то скорее всего это плохая иерархия. В вашей иерархии теряется весь смысл наследования - вынесение общего для нескольких классов функционала в базовый класс и уменьшение свяности (coupling) вашего приложения. К тому же есть ненулевая вероятность, что однажды вы сделаете понижающее преобразование объекта из другой ветки иерархии, что приведёт к вылету программы.

READ ALSO
Строки и слова

Строки и слова

Программа должна выводить, сколько раз каждое слово встречается в строке, но этого не происходитВот код:

193
Как уменьшить размер изображения в Qt?

Как уменьшить размер изображения в Qt?

Как реализовать программу, которая бы получала на вход изображение, изменяла его, а потом сохраняла новый вариант куда-нибудь в другое место?

338
Как распознать изображение средствами Qt?

Как распознать изображение средствами Qt?

Здравствуйте все, кто читает это! Интересует такой вопрос: Как разбить изображение на пиксели и обработать каждый из них? Или как получить...

345