多态
在基类(父类)使用 virtual,在派生类(子类)使用override 关键字。
允许子类重写(覆盖)父类提供的同名方法
示例
想象一个场景:你有一个“动物”类,它有“叫”这个方法。但有个问题,每个动物的叫声都不一样的。
cpp
class Animal {
public:
virtual void speak() {
cout << "动物叫" << endl;
}
};现在有两个子类:
cpp
class Dog : public Animal {
public:
void speak() override {
cout << "汪汪!" << endl;
}
};
class Cat : public Animal {
public:
void speak() override {
cout << "喵喵!" << endl;
}
};多态的核心:
cpp
Animal* animal1 = new Dog();
Animal* animal2 = new Cat();
animal1->speak(); // 输出"汪汪!"
animal2->speak(); // 输出"喵喵!"关键点:
- 同一个接口(函数成员):都是
animal->speak() - 不同实现:狗叫狗的声音,猫叫猫的声音
- 运行时决定:程序运行的时候才知道具体调用哪个
一句话总结:
多态就是父类指针指向子类对象,调用相同的方法,但执行不同的操作。
就像你按“播放”键:
- 在MP3上→播放音乐
- 在DVD上→播放视频
- 在手机上→播放视频或音乐
都是“播放”,但实际行为不同!
啥是“接口”
“接口”就是父类提供的那些可以被重写的函数(方法)。
更具体点:
cpp
class Shape { // 形状基类
public:
// 这两个函数就是“接口”
virtual double area() = 0; // 纯虚函数,必须被子类实现
virtual void draw() { // 虚函数,有默认实现
cout << "绘制形状" << endl;
}
};
class Circle : public Shape {
public:
double area() override { // 实现接口
return 3.14 * radius * radius;
}
void draw() override { // 实现接口
cout << "绘制圆形" << endl;
}
};关键理解:
- 接口 = 父类声明的虚函数(可以被子类重写的那些函数)
- 实现 = 子类对这些函数的具体定义
打个比方:
- 父类说:“我有两个接口:
area()计算面积,draw()绘制自己” - 圆形说:“我来实现这两个接口:
area()用πr²计算,draw()画个圈” - 矩形说:“我也实现:
area()用长×宽计算,draw()画个长方形”
多态的使用:
cpp
Shape* shape1 = new Circle();
Shape* shape2 = new Rectangle();
shape1->area(); // 调用Circle的area()
shape2->area(); // 调用Rectangle的area()
// 同样的shape指针,调用同样的area()函数名
// 但实际执行的是不同子类的实现一句话总结:
接口就是父类提供的“函数承诺”——“我的子类们都必须有这些函数,但具体实现可以不同。”多态就是通过这些接口函数调用不同子类的实现。