- C++
什么是虚函数?
- 2025-6-8 16:11:13 @
在C++中,虚函数(Virtual Function)是实现运行时多态(Runtime Polymorphism)的核心机制。它允许基类的指针或引用调用派生类中的重写函数,具体调用哪个版本的函数在运行时根据对象的实际类型决定,而不是编译时的静态类型。
虚函数的核心概念
-
声明方式
在基类中使用virtual
关键字声明的函数即为虚函数。例如:class Shape { public: virtual double area() const { return 0.0; } // 虚函数 };
-
重写(Override)
派生类可以提供虚函数的具体实现,称为“重写”。重写时函数签名(名称、参数、常量性)必须与基类一致:class Circle : public Shape { public: double area() const override { return 3.14 * radius * radius; } // 重写基类虚函数 private: double radius; };
-
动态绑定(Dynamic Binding)
通过基类指针或引用调用虚函数时,实际执行的是对象实际类型的函数版本,而非指针/引用的静态类型:Shape* shape = new Circle(5.0); shape->area(); // 调用 Circle::area(),而非 Shape::area()
虚函数的关键特性
-
运行时多态
虚函数实现了“一个接口,多种实现”的设计理念。例如,不同形状(圆形、矩形)可以通过基类指针调用各自的area()
函数。 -
虚函数表(VTable)
- 每个包含虚函数的类都有一个虚函数表,存储该类的虚函数地址。
- 每个对象包含一个指向虚函数表的指针(vptr),用于在运行时查找函数地址。
-
纯虚函数与抽象类
- 纯虚函数用
= 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
注意事项
-
性能开销
虚函数调用比普通函数略慢,因为需要通过虚函数表查找函数地址。 -
构造函数与析构函数
- 构造函数不能是虚函数(对象尚未完全创建)。
- 析构函数通常应该是虚函数,尤其是基类指针指向派生类对象时,确保正确释放资源:
class Base { public: virtual ~Base() {} // 虚析构函数 };
-
虚函数与默认参数
默认参数是静态绑定的,调用时根据指针/引用的类型确定,而非对象实际类型。
总结
虚函数是C++实现多态的关键机制,它允许通过基类接口调用派生类的特定实现,使代码更灵活、可扩展。合理使用虚函数可以构建出松耦合、易维护的面向对象系统。
0 条评论
目前还没有评论...