我在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();
答案 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
}