【C/C++】虚函数

发布于:2025-05-08 ⋅ 阅读:(31) ⋅ 点赞:(0)

📘 C++ 虚函数详解(Virtual Function)


📌 什么是虚函数?

虚函数(Virtual Function) 是 C++ 中实现运行时多态(Runtime Polymorphism) 的核心机制。

它允许派生类 重写(Override) 基类的函数实现,使得通过基类指针或引用调用函数时,能根据对象的实际类型动态绑定到对应的实现。


🔧 虚函数的作用

作用 说明
实现多态性 允许基类指针/引用指向派生类对象,并调用派生类的方法
接口设计 基类定义接口(纯虚函数),派生类实现具体功能
解耦代码 业务逻辑与具体实现分离,提高代码可维护性

🛠️ 使用方式

1. 声明虚函数

class Base {
public:
    virtual void show() { 
        std::cout << "Base class" << std::endl; 
    }
};

2. 派生类重写虚函数

class Derived : public Base {
public:
    void show() override {  // C++11 强制重写检查
        std::cout << "Derived class" << std::endl;
    }
};

3. 通过基类指针/引用调用

Base* ptr = new Derived();
ptr->show();  // 输出 "Derived class"

⚠️ 虚析构函数

当基类可能被继承时,必须将析构函数声明为虚函数,防止内存泄漏:

class Base {
public:
    virtual ~Base() {}  // 虚析构函数
};

🧠 虚函数表(vtable)与虚函数指针(vptr)

  • 虚函数表(vtable):每个含虚函数的类都有一个虚函数表,存储虚函数的地址。
  • 虚函数指针(vptr):每个对象隐式包含一个指向其类虚函数表的指针。

⚠️ 底层机制无需手动干预,但理解原理有助于优化设计


⚖️ 注意事项

限制项 说明
不能是静态函数 静态函数属于类而非对象,无法动态绑定
不能是友元函数 友元函数不属于类成员
默认参数值需谨慎 默认参数在编译时绑定,可能引发意外行为
性能开销 间接寻址调用,比普通函数慢 5-10 倍

📦 示例代码

#include <iostream>
using namespace std;

class Shape {
public:
    virtual void draw() { cout << "Shape" << endl; }
    virtual ~Shape() {}  // 虚析构函数
};

class Circle : public Shape {
public:
    void draw() override { cout << "Circle" << endl; }
};

class Rectangle : public Shape {
public:
    void draw() override { cout << "Rectangle" << endl; }
};

int main() {
    Shape* shapes[] = { new Circle(), new Rectangle() };
    for (auto s : shapes) {
        s->draw();  // 多态调用
        delete s;
    }
    return 0;
}

输出结果:

Circle
Rectangle

❓ 常见问题

问题 回答
虚函数可以是 inline 吗? ✅ 可以声明为 inline,但编译器会忽略 inline 优化
虚函数可以有默认参数吗? ✅ 可以,但建议保持参数一致以避免混淆
构造函数可以是虚函数吗? ❌ 不可以,构造期间对象类型未完全确定
虚函数可以是模板函数吗? ❌ 不支持虚模板函数,但可以有虚函数模板特化

🔒 纯虚函数与抽象类

纯虚函数 是没有实现的虚函数,用于定义接口:

class Interface {
public:
    virtual void method() = 0;  // 纯虚函数
};
  • 包含纯虚函数的类称为抽象类,不能直接实例化。
  • 派生类必须实现所有纯虚函数,否则自身也是抽象类。

📊 总结

核心要点 说明
多态性 通过虚函数实现运行时动态绑定
接口设计 纯虚函数定义接口,派生类实现细节
性能考量 虚函数调用有间接寻址开销
安全销毁 基类析构函数必须为虚函数
设计原则 对扩展开放,对修改关闭(OCP)

📝 设计建议

📌 设计建议:

  1. 仅对需要多态的函数使用 virtual
  2. 抽象类作为接口时,析构函数必须为虚函数。
  3. 使用 override 显式标记重写函数(C++11 起)。

术语对照

  • Virtual Function → 虚函数
  • Pure Virtual Function → 纯虚函数
  • Abstract Class → 抽象类
  • Runtime Polymorphism → 运行时多态


网站公告

今日签到

点亮在社区的每一天
去签到