小学生学C++编程语法知识(为什么抽象基类不能创建对象?)

小学生学C++编程语法知识(为什么抽象基类不能创建对象?)


C++面向对象:为什么抽象基类不能创建对象?

同学们,前面我们学习了:

  • 什么是

  • 什么是继承

  • 什么是虚函数

  • 什么是多态

今天我们学习一个很重要的概念:

为什么抽象基类不能创建对象?

这个问题在 GESP、CSP-J/S 中非常常见。


一、先回忆:什么是基类?

假设我们要设计一个动物系统。

有:

它们都是动物。

我们可以写:

class Animal { public: void eat() { cout << "吃东西" << endl; } };

然后:

class Dog : public Animal { }; class Cat : public Animal { };

这里:

Animal | -------------- | | Dog Cat

Animal 是:

父类(基类)

Dog、Cat 是:

子类(派生类)


二、普通基类可以创建对象

例如:

Animal a;

完全没有问题。


因为 Animal 自己是完整的。

它有:

吃东西()

这个功能。


所以:

Animal对象 { eat() }

可以存在。


但是问题来了:

如果 Animal 只是一个概念呢?

比如:

动物会叫。


但是:

狗怎么叫?

汪汪

猫怎么叫?

喵喵

鸟怎么叫?

叽叽

那么:

Animal 的叫声是什么?

不知道。


三、什么是抽象基类?

我们看:

class Animal { public: virtual void speak() = 0; };

这里:

virtual void speak() = 0;

叫:

纯虚函数(pure virtual function)


意思:

“我只规定规则,但是不写具体内容。”

例如:

动物必须会叫

但是:

怎么叫?

交给孩子。


然后:

狗:

class Dog : public Animal { public: void speak() { cout<<"汪汪"<<endl; } };

猫:

class Cat : public Animal { public: void speak() { cout<<"喵喵"<<endl; } };

结构:

Animal (会叫,但是不知道怎么叫) | ---------------- | | Dog Cat (汪汪) (喵喵)

四、为什么 Animal 不能创建对象?

如果写:

Animal a;

C++ 会报错。

为什么?


因为:

Animal 里面有:

virtual void speak() = 0;

它只是告诉大家:

必须有叫的方法

但是它自己没有:

叫的方法

所以:

Animal对象 { ? }

不完整。


打个比方:

动物学校

校长说:

所有学生必须会唱歌。

但是校长没有规定:

唱什么歌。


现在来了一个学生:

Animal学生

老师问:

请唱歌。

学生:

我不知道唱什么。

所以:

这个学生不能报名。


五、抽象类为什么存在?

有人问:

既然不能创建对象,

那为什么还要写它?

这是重点!

抽象类的作用:

为子类制定统一规则。


例如:

游戏里面:

角色

有:

  • 战士

  • 法师

  • 弓箭手


设计:

class Role { public: virtual void attack()=0; };

意思:

所有角色必须攻击。


战士:

class Warrior:public Role { public: void attack() { cout<<"挥剑攻击"; } };

法师:

class Mage:public Role { public: void attack() { cout<<"释放魔法"; } };

以后游戏写:

Role *p;

可以:

p=new Warrior(); p->attack();

也可以:

p=new Mage(); p->attack();

这就是:

多态


六、抽象类和普通类的区别

普通类抽象类
有没有纯虚函数没有
能否创建对象可以不可以
作用描述具体东西规定规则
是否可以继承可以主要给子类继承

七、判断一个类是不是抽象类

非常简单:

看有没有:

=0

例如:

不是抽象类

class A { public: virtual void fun() { } };

可以:

A a;

是抽象类

class A { public: virtual void fun()=0; };

不能:

A a;

八、抽象类可以有普通函数吗?

当然可以。

例如:

class Animal { public: virtual void speak()=0; void eat() { cout<<"吃东西"; } };

这里:

Animal | |-- speak() | (没有实现) | |-- eat() (已经实现)

子类继承:

class Dog:public Animal { public: void speak() { cout<<"汪汪"; } };

然后:

Dog d; d.eat(); d.speak();

输出:

吃东西 汪汪

九、抽象类可以有构造函数吗?

可以。

例如:

class Animal { public: Animal() { cout<<"动物出生"; } virtual void speak()=0; };

虽然:

Animal a;

不允许。

但是:

创建:

Dog d;

时:

执行顺序:

Animal构造函数 ↓ Dog构造函数

因为:

先出生父亲,

再出生孩子。


十、抽象类最重要的应用:接口思想

很多时候,我们不是为了创建对象。

而是为了:

规定所有子类必须完成什么功能。


例如:

支付系统:

Payment | -------------------- | | 支付宝 微信

抽象类:

class Payment { public: virtual void pay()=0; };

支付宝:

class AliPay:public Payment { void pay() { cout<<"支付宝支付"; } };

微信:

class WeChatPay:public Payment { void pay() { cout<<"微信支付"; } };

以后:

Payment *p;

不用管具体是谁。

这就是:

统一接口 + 多态

十、一句话总结(考试重点)

抽象基类因为包含至少一个纯虚函数,表示它是不完整的“规则模板”,没有具体实现,所以不能创建对象;它的作用是让派生类继承并实现这些纯虚函数,从而实现多态。

记忆口诀:

有纯虚函数 ↓ 抽象类 ↓ 不能创建对象 ↓ 只能被继承 ↓ 实现多态

对于 GESP/CSP-J ,同学们可以把它和前面学过的知识串起来:

继承 ↓ 虚函数 ↓ 纯虚函数 ↓ 抽象基类 ↓ 多态

这条链是 C++ 面向对象最核心的一条线。