在C++中,虚函数(Virtual Function)是实现运行时多态(Runtime Polymorphism)的核心机制。它允许基类的指针或引用调用派生类中的重写函数,具体调用哪个版本的函数在运行时根据对象的实际类型决定,而不是编译时的静态类型。

虚函数的核心概念

  1. 声明方式
    在基类中使用 virtual 关键字声明的函数即为虚函数。例如:

    class Shape {
    public:
        virtual double area() const { return 0.0; } // 虚函数
    };
    
  2. 重写(Override)
    派生类可以提供虚函数的具体实现,称为“重写”。重写时函数签名(名称、参数、常量性)必须与基类一致:

    class Circle : public Shape {
    public:
        double area() const override { return 3.14 * radius * radius; } // 重写基类虚函数
    private:
        double radius;
    };
    
  3. 动态绑定(Dynamic Binding)
    通过基类指针或引用调用虚函数时,实际执行的是对象实际类型的函数版本,而非指针/引用的静态类型:

    Shape* shape = new Circle(5.0);
    shape->area(); // 调用 Circle::area(),而非 Shape::area()
    

虚函数的关键特性

  1. 运行时多态
    虚函数实现了“一个接口,多种实现”的设计理念。例如,不同形状(圆形、矩形)可以通过基类指针调用各自的 area() 函数。

  2. 虚函数表(VTable)

    • 每个包含虚函数的类都有一个虚函数表,存储该类的虚函数地址。
    • 每个对象包含一个指向虚函数表的指针(vptr),用于在运行时查找函数地址。
  3. 纯虚函数与抽象类

    • 纯虚函数用 = 0 声明,没有具体实现:
      virtual double area() const = 0; // 纯虚函数
      
    • 包含纯虚函数的类是抽象类,无法实例化,只能作为基类使用。

为什么需要虚函数?

示例场景
假设你有一个图形库,需要计算不同形状的面积。通过虚函数,可以统一调用基类的 area() 函数,实际执行时根据对象类型自动选择正确的实现:

#include <iostream>
using namespace std;

class Shape {
public:
    virtual double area() const { return 0.0; } // 虚函数
};

class Circle : public Shape {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}
    double area() const override { return 3.14 * radius * radius; }
};

class Rectangle : public Shape {
private:
    double width, height;
public:
    Rectangle(double w, double h) : width(w), height(h) {}
    double area() const override { return width * height; }
};

int main() {
    Shape* shapes[2];
    shapes[0] = new Circle(5.0);
    shapes[1] = new Rectangle(3.0, 4.0);

    for (int i = 0; i < 2; i++) {
        cout << "Area: " << shapes[i]->area() << endl; // 动态调用正确的 area()
    }

    delete shapes[0];
    delete shapes[1];
    return 0;
}

输出

Area: 78.5
Area: 12

注意事项

  1. 性能开销
    虚函数调用比普通函数略慢,因为需要通过虚函数表查找函数地址。

  2. 构造函数与析构函数

    • 构造函数不能是虚函数(对象尚未完全创建)。
    • 析构函数通常应该是虚函数,尤其是基类指针指向派生类对象时,确保正确释放资源:
      class Base {
      public:
          virtual ~Base() {} // 虚析构函数
      };
      
  3. 虚函数与默认参数
    默认参数是静态绑定的,调用时根据指针/引用的类型确定,而非对象实际类型。

总结

虚函数是C++实现多态的关键机制,它允许通过基类接口调用派生类的特定实现,使代码更灵活、可扩展。合理使用虚函数可以构建出松耦合、易维护的面向对象系统。

0 条评论

目前还没有评论...