为什么我们使用多态性指针?

时间:2017-01-10 12:08:39

标签: c++ polymorphism

我在youtube上观看来自thenewboston的教程,我对多态性几乎没有任何疑问。这是他的代码:

#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 个答案:

答案 0 :(得分:3)

  

我可以像{[1]}这样编写代码[...]

当然,你可以!原因是您的新示例不使用多态行为。与原始示例不同,原始示例隐藏了编译时代码中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 也不会因object slicing而显示多态行为。

您需要使setPowerAndAttack指针或引用以保持多态行为:

enemy

非常重要:您需要在void setPowerAndAttack(Enemy& enemy, int power) // ^ 课程中设置attack函数virtual才能拥有任何多态行为。观看视频时不清楚这一点:

Enemy

答案 1 :(得分:2)

  

为什么我们使用多态性指针?

因为间接是实现动态多态性所必需的。指针是一种间接形式,也是用于多态性的引用。

  

我可以像这样在main()中编写代码(或者不应该我和为什么?):

你可以,你应该。所示的类层次结构是非多态继承的示例。间接增加没有任何用处。

答案 2 :(得分:1)

您的示例不使用多态。

多态性可以简化为通过通用接口提供不同的功能。想想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
}