Почему мы используем указатели с полиморфизмом?

Я смотрю учебники из youewboston на YouTube, и у меня есть несколько вопросов о полиморфизме. Вот его код:

#include <iostream>
using namespace std;
class Enemy{


   protected:
   int attackPower;
public:
    void setAttackPower(int a){
    attackPower=a;
    }
};

class Ninja:public Enemy{
public:
    void attack(){
    cout<<"I am a ninja,ninja chop! -"<<attackPower<<endl;}
};

class Monster:public Enemy{
public:
void attack() {
cout<<"monnster must eat you!!! -"<<attackPower<<endl;
}
};

int main()
{
    Ninja n;
    Monster m;
    Enemy *enemy1=&n;
    Enemy *enemy2=&m;
    enemy1->setAttackPower(29);
    enemy2->setAttackPower(99);
    n.attack();
    m.attack();

}

Мой вопрос: могу ли я написать код в main() следующим образом (или я не должен и ПОЧЕМУ??):

Ninja n;
Monster m;
//Enemy *enemy1=&n;
//Enemy *enemy2=&m;
//enemy1->setAttackPower(29);
//enemy2->setAttackPower(99);
n.setAttackPower(99);
m.setAttackPower(29);
n.attack();
m.attack();

3 ответа

Решение

Могу ли я написать код в main() как это [...]

Абсолютно, вы можете! Причина этого в том, что ваш новый пример не использует полиморфное поведение. В отличие от оригинального примера, который скрывал знание типа времени выполнения Enemy объекты из кода времени компиляции, ваш переписанный код сохраняет типы доступны.

Вот что не будет работать без указателя или ссылки:

void setPowerAndAttack(Enemy enemy, int power) {
//                     ^^^^^^^^^^^
//  This is not going to work without pointer/reference
    enemy.setAttackPower(power);
    attack();
}
...
Ninja n;
Monster m;
setPowerAndAttack(n, 99);
setPowerAndAttack(m, 29);

Хотя код будет компилироваться, Enemy в setPowerAndAttack не будет демонстрировать полиморфное поведение из-за нарезки объектов.

Вам нужно сделать enemy указатель или ссылка для сохранения полиморфного поведения:

void setPowerAndAttack(Enemy& enemy, int power)
//                          ^

Очень важно: нужно сделать attack функция virtual в Enemy класс для того, чтобы иметь какое-либо полиморфное поведение на всех. Это не ясно из просмотра видео:

class Enemy {
protected:
   int attackPower;
public:
    void setAttackPower(int a) {
        attackPower=a;
    }
    virtual void attack();      // <<== Add this line
    virtual ~Enemy() = default; // <<== Add a virtual destructor
};

Почему мы используем указатели с полиморфизмом?

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

Могу ли я написать код в main() следующим образом (или я не должен и почему?):

Вы можете, и вы должны. Показанная иерархия классов в является примером неполиморфного наследования. Направление не добавляет ничего полезного.

Ваш пример не использует полиморфизм.

Полиморфизм может быть упрощен как предоставление различных функциональных возможностей через общий интерфейс. Представьте себе USB-устройства: клавиатура и флэш-накопитель используют один и тот же USB-порт, но предоставляют разную функциональность.

Этот пример будет использовать полиморфизм:

#include <iostream>
using namespace std;
class Enemy
{
protected:
    int attackPower;

public:
    virtual ~Enemy() = default;
    virtual void attack() = 0;
    void setAttackPower(int a) { attackPower = a; }
};

class Ninja : public Enemy
{
public:
    void attack() 
    { 
        cout << "I am a ninja,ninja chop! -" << attackPower << endl; 
    }
};

class Monster : public Enemy
{
public:
    void attack() 
    { 
        cout << "monnster must eat you!!! -" << attackPower << endl; 
    }
};

int main()
{
    Ninja n;
    Monster m;
    Enemy* enemy1 = &n;
    Enemy* enemy2 = &m;
    enemy1->setAttackPower(29); // not polymorphism: interface and functionality are from Enemy
    enemy2->setAttackPower(99); // not polymorphism: interface and functionality are from Enemy
    enemy1->attack(); // polymorphism: interface of Enemy, functionality of Ninja
    enemy2->attack(); // polymorphism: interface of Enemy, functionality of Monster
}
Другие вопросы по тегам