Skip to content

多态

在基类(父类)使用 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();  // 输出"喵喵!"

关键点

  1. 同一个接口(函数成员):都是animal->speak()
  2. 不同实现:狗叫狗的声音,猫叫猫的声音
  3. 运行时决定:程序运行的时候才知道具体调用哪个

一句话总结

多态就是父类指针指向子类对象,调用相同的方法,但执行不同的操作。

就像你按“播放”键:

  • 在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;
    }
};

关键理解:

  1. 接口 = 父类声明的虚函数(可以被子类重写的那些函数)
  2. 实现 = 子类对这些函数的具体定义

打个比方:

  • 父类说:“我有两个接口: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()函数名
// 但实际执行的是不同子类的实现

一句话总结:

接口就是父类提供的“函数承诺”——“我的子类们都必须有这些函数,但具体实现可以不同。”多态就是通过这些接口函数调用不同子类的实现。