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

c++中虚函数表属于类还是属于对象?

在 C++ 中,虚函数表(Virtual Table,简称 vtable) 是实现多态性的关键机制之一。关于虚函数表的归属问题,常见的疑问是:

“虚函数表属于类?还是属于对象?”

答案是:

虚函数表属于类,而不是每个对象。

然而,为了更深入地理解这一概念,下面将详细解释虚函数表(vtable)和虚指针(vptr)的关系,以及它们如何在类和对象中协同工作。


1. 虚函数表(vtable)概述

  • 虚函数表(vtable):这是一个由编译器生成的静态数据结构,用于支持运行时的动态绑定。每个包含虚函数的类(基类或派生类)都有一个对应的虚函数表。

  • 虚指针(vptr):每个对象内部通常包含一个隐藏的指针,称为虚指针,指向所属类的虚函数表。这个指针由编译器自动管理,程序员通常无需直接操作。


2. 虚函数表属于类

  • 类级别的虚函数表

    • 单一实例:对于每个具有虚函数的类,编译器生成一个唯一的虚函数表。无论创建多少个该类的对象,所有对象共享同一个虚函数表。

    • 内容:虚函数表中存储的是该类中所有虚函数的地址。如果派生类覆写了基类的虚函数,虚函数表中的对应条目将指向派生类的实现。

    • 示例

      class Base {
      public:
          virtual void func1() { /* ... */ }
          virtual void func2() { /* ... */ }
      };
      
      class Derived : public Base {
      public:
          void func1() override { /* ... */ } // 覆写 Base::func1
          void func3() { /* 非虚函数 */ }
      };
      
      • Base 类有一个虚函数表 vtable_Base,包含 func1func2 的地址。
      • Derived 类有一个虚函数表 vtable_Derivedfunc1 指向 Derived::func1func2 继承自 Base,如果未覆写则指向 Base::func2,并且新增的 func3 不在虚函数表中(因为它不是虚函数)。

3. 虚指针属于对象

  • 对象级别的虚指针(vptr)

    • 每个对象都有一个虚指针:当创建一个对象时,编译器会自动在对象内嵌入一个指向其类的虚函数表的指针(vptr)。

    • 指向虚函数表:这个虚指针指向所属类的虚函数表。例如,Base 类的对象指向 vtable_BaseDerived 类的对象指向 vtable_Derived

  • 运行时多态的实现

    • 当通过基类指针或引用调用虚函数时,程序会通过 vptr 查找虚函数表,从而调用实际对象类中对应的函数实现,实现动态绑定。
  • 示例

    Base* obj = new Derived();
    obj->func1(); // 调用 Derived::func1
    obj->func2(); // 调用 Base::func2(如果 Derived 未覆写 func2)
    
    • 尽管 objBase 类型的指针,但它实际指向一个 Derived 对象。
    • objvptr 指向 vtable_Derived,因此调用 func1 时会执行 Derived::func1,而调用 func2 时,如果 Derived 没有覆写 func2,则执行 Base::func2

4. 视觉化理解

类和虚函数表的关系

类 Base ------------------> vtable_Base
    | func1 -> Base::func1
    | func2 -> Base::func2

类 Derived ---------------> vtable_Derived
    | func1 -> Derived::func1
    | func2 -> Base::func2

对象和虚指针的关系

对象 baseObj (Base 类型)
    | vptr -> vtable_Base

对象 derivedObj (Derived 类型)
    | vptr -> vtable_Derived

5. 总结

  • 虚函数表(vtable)类级别 的数据结构,每个具有虚函数的类都有自己的虚函数表。

  • 虚指针(vptr)对象级别 的,每个对象包含一个指向其所属类虚函数表的指针。

  • 这种设计使得不同类的对象可以共享相同的虚函数表(如果它们没有覆写虚函数),同时支持运行时的多态性,通过虚指针动态绑定到正确的函数实现。

  • override 关键字 主要用于在编译时确保子类正确覆写基类的虚函数,它本身并不直接影响虚函数表的结构或行为,但正确使用 override 可以避免潜在的覆写错误,确保多态性正常工作。


http://www.kler.cn/news/364567.html

相关文章:

  • 人工智能算法之双倍体遗传算法(DGA)
  • 自学C语言——函数(全)
  • 信息安全工程师(55)网络安全漏洞概述
  • mysqld.log文件过大,清理后不改变所属用户
  • 延迟队列实现及其原理详解
  • Django学习- ORM基础操作_创建数据
  • Ubuntu20.04 更新Nvidia驱动 + 安装CUDA12.1 + cudnn8.9.7
  • 【数据结构与算法】力扣 46. 全排列
  • 中国人寿财险青岛市分公司引领科技金融新风尚
  • HarmonyOS 5.0应用开发——应用打包HAP、HAR、HSP
  • 新160个crackme - 082-phox.1
  • Elasticsearch在分布式集群中进行数据分片的策略能否完全避免数据热点?数据分片分布不均会导致性能瓶颈吗?如何通过实践优化分片分布?
  • 本地生活平台开发搭建方案 同城O2O电商平台推广运营
  • OpenCV视觉分析之运动分析(2)背景减除类:BackgroundSubtractorKNN的使用
  • 缓存雪崩是什么
  • SparseRCNN 模型,用于目标检测任务
  • 云计算行业应用实训室建设方案
  • es 常用命令(已亲测)
  • Unity编辑器 连接不到SteamVR问题记录
  • 一个批量输出PDF页数的python程序
  • 常用MQ组件选型时需要考虑的问题
  • 独家大模型经典面试秘籍:问题答案超详细,收藏此文就够咯
  • AnaTraf | 探讨TCP握手时延
  • JavaScript正则表达式利器:exec()方法深度解析与应用实例
  • pnpm : 无法加载文件...
  • 用户画像中不同机器学习模型的优缺点和适用场景