我是C ++面向对象编程的初学者。我正在学习"抽象课程"示例代码是:
#include <iostream>
using namespace std;
class Enemy {
public:
virtual void attack() = 0;
};
class Ninja: public Enemy {
public:
void attack() {
cout << "Ninja!"<<endl;
}
};
class Monster: public Enemy {
public:
void attack() {
cout << "Monster!"<<endl;
}
};
int main()
{
Ninja n;
Monster m;
Enemy *e1 = &n;
Enemy *e2 = &m;
e1->attack();
e2->attack();
return 0;
}
我想要理解的是为什么我只能使用派生类的对象来直接访问派生类成员&#34;。&#34;运算符(它有效,但不建议为什么?)。
像这样:
int main()
{
Ninja n;
Monster m;
Enemy *e1 = &n;
Enemy *e2 = &m;
//e1->attack();
//e2->attack();
n.attack();
m.attack();
return 0;
}
我知道有些情况我们需要通过基类来访问派生类的成员(我认为这是所有程序员通常使用的),但我不知道真实世界的实现一种情况(为什么我们不能直接进行,为什么要通过基类的指针?)。
如果有人能澄清我的怀疑,我会很高兴。答案 0 :(得分:4)
敌人(std::vector<Enemy*>
)的集合可以拥有忍者和怪物。忍者的集合只能包含忍者,而怪物的集合只能包含怪物。
抽象基类为子类提供了一个通用接口,但是抽象基类的实例没有实际意义(否则你不会使基类抽象)。
答案 1 :(得分:0)
其余部分已经涵盖了很好的购买其他答案,但“为什么指针?”被忽略了。
每个子类具有不同的内容并且可能具有不同的大小。如果没有引用,程序必须知道分配存储的确切大小。要求所有子类具有相同的大小是非启动性的,因为这只是面对C ++意识形态,只需支付您使用的内容,并且需要修改以前编译的代码(新模块添加新的子类,所有现有模块也必须改变)。此外,基类没有合理的方法来了解有关其子类的详细信息(以及为什么不应该这样做的许多原因),这包括了解大小。
通过引用,没有人关心大小或实现细节。该对象是一些未知大小的匿名内存块,如果对象是多态的,它包含自己的访问规则和指令(这是probably a "v-table",但只要结果满足,C ++就不关心使用什么voodoo。标准)。