多态
多态
今天我们来学一下多态这个概念
为什么需要多态?
假如我们想要定义一个动物叫的函数,如果没有使用多态,那么将会是这样的
#include <iostream>
using namespace std;
// 定义狗类
class Dog {
public:
// 狗的叫
void bark() {
cout << "小狗:汪汪汪~" << endl;
}
};
// 定义猫类
class Cat {
public:
// 猫的叫
void meow() {
cout << "小猫:喵喵喵~" << endl;
}
};
// 定义鸡类
class Chicken {
public:
// 鸡的叫
void cluck() {
cout << "小鸡:咯咯咯~" << endl;
}
};
// 主函数:让不同动物叫
int main() {
Dog dog;
Cat cat;
Chicken chicken;
// 调用不同的函数,才能让不同动物叫
dog.bark();
cat.meow();
chicken.cluck();
return 0;
}
可以看到,代码是及其繁琐且复杂的,而且可读性也不强,所以我们引入了多态这一概念
实现多态的三个前提条件
- 必须存在继承关系(比如要写猫叫与狗叫的逻辑前提为猫和狗的父类为动物类)
- 必须有由父类指向的指针
- 子类必须重写父类的虚函数(virtual)
如果有不懂的词,不用着急,接下来会继续演示深入
虚函数
下面来介绍一下虚函数这一个概念
虚函数相当于是子类允许重写函数的开关,如果没有声明为虚函数,那么即使重写了,也无法触发多态
下面是使用虚函数实现多态的一个示例
class Animal { // 父类
public:
virtual void cry() { // 虚函数
cout << "动物的叫声" << endl;
}
};
class Dog : public Animal { // 子类继承父类
public:
// 正确重写:函数名、返回值、参数列表完全和父类一致
void cry() {
cout << "小狗:汪汪汪~" << endl;
}
};
重写
子类定义一个和父类虚函数完全一致的函数,替换父类的默认实现,实现子类专属逻辑 —— 这是多态的核心行为
子类重写的函数,必须和父类虚函数满足 函数名相同、返回值相同、参数列表完全相同(个数、类型、顺序都一致),否则编译器会认为是子类新增函数,而非重写,无法触发多态。
重写检测
子类重写的可选写法:override 关键字(可加可不加)
C++11 新增 override 关键字,写在子类重写函数的末尾,强制编译器检查是否满足重写规则—— 如果不满足(比如函数名写错、参数不一致),编译器会直接报错,避免新手因笔误导致多态失效。
指针与引用
使用指针实现多态
anm* p1 = &a;
p1->cry();
输出
喵喵喵~
使用引用实现多态
void letAnimalCry(Animal& animal) {
animal.cry();
}
输出
喵喵喵~
如果既不使用指针,也不使用引用,那么多态将会失效
动物叫 //(未触发多态)

浙公网安备 33010602011771号