抽象基类(第 13 章)

← 返回虚函数 | ← 主页


目录


🔴纯虚函数

🔺在虚函数声明末尾加 = 0,该函数为纯虚函数,类变为抽象类

class Shape {
public:
    virtual double area() = 0;   // 纯虚函数,无需实现
    virtual void draw() = 0;     // 纯虚函数
    virtual ~Shape()           // 析构函数仍需是虚函数
};

🔺纯虚函数可以有实现体(少见),但派生类仍必须重写:

virtual void func() = 0;  // 声明为纯虚
 
void Base::func() { /* 可以有实现,但派生类必须重写 */ }

🔴抽象类的规则

🔺含有至少一个纯虚函数的类是抽象类

  • 不能实例化Shape s; ❌ 编译错误
  • 可以有指针/引用Shape* p = new Circle();
  • 派生类必须实现所有纯虚函数,否则派生类也是抽象类,同样不能实例化
class Circle : public Shape {
    double r;
public:
    Circle(double r) : r(r) {}
    double area() override { return 3.14159 * r * r; }  // ✅ 实现纯虚函数
    void draw() override { cout << "Drawing circle\n"; }
};
 
// Shape s;              // ❌ 抽象类不能实例化
Shape* p = new Circle(5.0);  // ✅ 基类指针指向派生类对象
cout << p->area();            // 动态绑定,调用 Circle::area
delete p;

🔺若派生类只实现了部分纯虚函数,该派生类仍是抽象类:

class PartialShape : public Shape {
public:
    double area() override { return 0; }
    // draw() 未实现 → PartialShape 仍是抽象类
};
 
// PartialShape ps;  // ❌ 仍不能实例化

🔴抽象类的用途

🔺定义接口规范:强制所有派生类实现特定方法,保证多态行为一致

class Animal {
public:
    virtual void speak() = 0;   // 所有动物必须实现 speak
    virtual void move() = 0;    // 所有动物必须实现 move
    virtual ~Animal() {}
};
 
class Dog : public Animal {
public:
    void speak() override { cout << "Woof\n"; }
    void move() override { cout << "Run\n"; }
};
 
class Bird : public Animal {
public:
    void speak() override { cout << "Tweet\n"; }
    void move() override { cout << "Fly\n"; }
};
 
// 统一接口处理不同类型
void makeAnimalAct(Animal* a) {
    a->speak();  // 动态绑定,自动调用正确的实现
    a->move();
}

🔴纯虚函数 vs 虚函数

特性虚函数纯虚函数
语法virtual void f()virtual void f() = 0
有无默认实现无(= 0)
派生类是否必须重写否(可继承默认实现)是(否则派生类也是抽象类)
类能否实例化不能(含纯虚函数 = 抽象类)
用途提供默认行为,允许重写定义接口,强制派生类实现

本节小结

要点说明
纯虚函数= 0,无需实现,强制派生类重写
抽象类含纯虚函数,不能实例化,但可以有指针/引用
派生类必须全实现未实现所有纯虚函数的派生类仍是抽象类
接口设计抽象基类用于定义统一接口,配合多态使用