当前位置: 首页 > news >正文

C++中通过虚函数实现多态的原理

C++中通过虚函数实现多态的原理

我们都知道C++是通过虚函数实现多态的,那么其中的原理是什么呢?

在C++中,多态性是一种重要的特性,它允许通过基类指针或引用来调用派生类中的函数。多态性主要分为两种:编译时多态(主要通过函数重载和模板实现)和运行时多态(主要通过虚函数实现)。C++中通过虚函数实现的多态主要是运行时多态(动态多态),其原理主要基于虚函数表(vtable)和虚函数指针(vptr)。

1. 虚函数的定义

虚函数是在基类中使用virtual关键字声明的成员函数。例如:

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

当一个类的成员函数被声明为虚函数后,C++运行时系统会为该类及其派生类提供动态绑定的机制。

2. 虚函数表(vtable)

虚函数表是一个由编译器生成的数组,其中存储了类中所有虚函数的地址。每个包含虚函数的类都有一个唯一的虚函数表。例如:

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

对于Base类,编译器会为其生成一个虚函数表,其中包含showdisplay的地址。

3. 虚函数指针(vptr)

每个包含虚函数的类的对象都会有一个隐藏的成员变量——虚函数指针(vptr)。这个指针指向该对象所属类的虚函数表。当对象被创建时,构造函数会初始化这个指针,使其指向正确的虚函数表。

4. 多态的实现原理

当通过基类指针或引用调用虚函数时,C++运行时系统会通过对象的vptr找到对应的vtable,然后通过vtable找到正确的虚函数地址并调用。这个过程称为动态绑定或晚期绑定。

#include <iostream>
using namespace std;

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

class Derived : public Base {
public:
    void show() override {
        cout << "Derived::show" << endl;
    }
};

int main() {
    Base* ptr;
    Base base;
    Derived derived;

    ptr = &base;
    ptr->show();  // 输出:Base::show

    ptr = &derived;
    ptr->show();  // 输出:Derived::show

    return 0;
}

解释:

  1. Base base对象:
    • base对象的vptr指向Base类的vtable。
    • Base类的vtable中存储了Base::show的地址。
    • 当调用ptr->show()时,运行时通过ptr对象的vptr找到Base类的vtable,并调用Base::show
  2. Derived derived对象:
    • derived对象的vptr指向Derived类的vtable。
    • Derived类的vtable中存储了Derived::show的地址(覆盖了Base::show)。
    • 当调用ptr->show()时,运行时通过ptr对象的vptr找到Derived类的vtable,并调用Derived::show

5. 虚函数表的存储结构

假设Base类和Derived类的虚函数表存储如下:

  • Base类的vtable:
    • Base::show
    • Base::display(如果有其他虚函数)
  • Derived类的vtable:
    • Derived::show(覆盖了Base::show
    • Base::display(如果没有覆盖,仍然指向基类的虚函数)

6. 多态的条件

要实现通过虚函数的多态,必须满足以下条件:

  1. 继承关系: 派生类继承自基类。
  2. 虚函数: 基类中必须有虚函数。
  3. 覆盖: 派生类覆盖了基类的虚函数。
  4. 使用基类指针或引用: 通过基类指针或引用调用虚函数。

7. 总结

通过虚函数实现多态的核心是虚函数表(vtable)和虚函数指针(vptr)。vtable存储了类中虚函数的地址,vptr指向对象所属类的vtable。运行时通过vptr找到正确的vtable,再通过vtable找到正确的虚函数地址并调用,从而实现动态绑定。

这种机制使得程序能够在运行时根据对象的实际类型调用对应的虚函数,而不是根据指针或引用的类型,从而实现了多态。

相关文章:

  • 优化Go错误码管理:构建清晰、优雅的HTTP和gRPC错误码规范
  • 一文掌握 RAG 的原理和对应的2个案例
  • 江苏无锡一家汽车零部件企业终止,拓展氢燃料电池存不确定性
  • Python说明
  • Linux 进程的创建、终止、等待与程序替换函数 保姆级讲解
  • Qt QML实现鼠标自由选择不规则区域进行截图
  • 编程自学指南:java程序设计开发,Java I/O流,为什么需要I/O流?,Java I/O体系结构,字节流,字符流,对象流与序列化
  • 深入理解Spring Boot:快速构建现代化的Java应用
  • C++中,存储持续性、作用域和链接性
  • 一般机器学习有哪些算法?
  • python笔记2
  • LeeCode题库第643题
  • 用Maven创建只有POM文件的项目
  • MCU的工作原理:嵌入式系统的控制核心
  • 解决 Docker 镜像拉取超时问题:配置国内镜像源
  • 【深度学习|目标检测】YOLO系列anchor-based原理详解
  • 注意力机制,层归一化,RBA。KAN-ODE,小波KAN
  • 提升开发效率的FPGA/IC小工具
  • 文件解析漏洞详解
  • 微软 System Center Configuration Manager(SCCM)的组件文件
  • 同济大学党委常务副书记冯身洪履新中国科协党组副书记
  • 上影节开幕影片《酱园弄·悬案》,陈可辛执导,章子怡主演
  • 文化破冰,土耳其亚美尼亚合拍摄影大师阿拉·古勒传记片
  • 和平会谈两天后,俄对乌发动冲突爆发以来最大规模无人机袭击
  • 广东信宜一座在建桥梁暴雨中垮塌,镇政府:未造成人员伤亡
  • 媒体评教师拎起学生威胁要扔下三楼:师风师德不能“悬空”