C++多态虚函数表详解(多重继承、多继承情况)

C++多态虚函数表详解(多重继承、多继承情况)本文关键词 C 多态虚函数表虚函数指针动态绑定概述 C 相对其他面向对象语言来说 之所以灵活 高效 很大程度的占比在于其多态技术和模板技术 C 虚函数表是支撑 C 多态的重要技术 它是 C 动态绑定技术的核心 本文章将着重图解虚函数表相关知识 在阅读本文前 博主已经默认你已经学习了 C 多态的语法 并且通过代码实践过

本文关键词:C++ 多态 多继承 多重继承 虚函数表 虚函数指针 动态绑定

一、多态起手式以及内存分布

二、类的虚函数表与类实例的虚函数指针

首先不考虑继承的情况。如果一个类中有虚函数,那么该类就有一个虚函数表
这个虚函数表是属于类的,所有该类的实例化对象中都会有一个虚函数表指针去指向该类的虚函数表。
从第一部分的图中我们也能看到,一个类的实例要么在堆上,要么在栈上。也就是说一个类可以有很多很多个实例。但是!一个类只能有一个虚函数表。在编译时,一个类的虚函数表就确定了,这也是为什么它放在了只读数据段中。
这里写图片描述
三、多态代码及多重继承情况








class ClassA { public: ClassA() { cout << "ClassA::ClassA()" << endl; } virtual ~ClassA() { cout << "ClassA::~ClassA()" << endl; } void func1() { cout << "ClassA::func1()" << endl; } void func2() { cout << "ClassA::func2()" << endl; } virtual void vfunc1() { cout << "ClassA::vfunc1()" << endl; } virtual void vfunc2() { cout << "ClassA::vfunc2()" << endl; } private: int aData; }; class ClassB : public ClassA { public: ClassB() { cout << "ClassB::ClassB()" << endl; } virtual ~ClassB() { cout << "ClassB::~ClassB()" << endl; } void func1() { cout << "ClassB::func1()" << endl; } virtual void vfunc1() { cout << "ClassB::vfunc1()" << endl; } private: int bData; }; class ClassC : public ClassB { public: ClassC() { cout << "ClassC::ClassC()" << endl; } virtual ~ClassC() { cout << "ClassC::~ClassC()" << endl; } void func2() { cout << "ClassC::func2()" << endl; } virtual void vfunc2() { cout << "ClassC::vfunc2()" << endl; } private: int cData; }; 
ClassA *a = new ClassB(); a->func1(); // "ClassA::func1()" 隐藏了ClassB的func1() a->func2(); // "ClassA::func2()" a->vfunc1(); // "ClassB::vfunc1()" 重写了ClassA的vfunc1() a->vfunc2(); // "ClassA::vfunc2()" 

这个结果不难想象,看上图,ClassA类型的指针a能操作的范围只能是黑框中的范围,之所以实现了多态完全是因为子类的虚函数表指针与虚函数表的内容与基类不同
这个结果已经说明了C++的隐藏、重写(覆盖)特性。

ClassA* a = new ClassC; a->func1(); // "ClassA::func1()" 隐藏ClassB::func1() a->func2(); // "ClassA::func2()" 隐藏ClassC::func2() a->vfunc1(); // "ClassB::vfunc1()" ClassB把ClassA::vfunc1()覆盖了 a->vfunc2(); // "ClassC::vfunc2()" ClassC把ClassA::vfunc2()覆盖了 ClassB* b = new ClassC; b->func1(); // "ClassB::func1()" 有权限操作时,子类优先 b->func2(); // "ClassA::func2()" 隐藏ClassC::func2() b->vfunc1(); // "ClassB::vfunc1()" ClassB把ClassA::vfunc1()覆盖了 b->vfunc2(); // "ClassB::vfunc2()" ClassC把ClassA::vfunc2()覆盖了 

四、多继承下的虚函数表 (同时继承多个基类)

多继承是指一个类同时继承了多个基类,假设这些基类都有虚函数,也就是说每个基类都有虚函数表,那么该子类的逻辑结果和虚函数表是什么样子呢?

class ClassA1 { public: ClassA1() { cout << "ClassA1::ClassA1()" << endl; } virtual ~ClassA1() { cout << "ClassA1::~ClassA1()" << endl; } void func1() { cout << "ClassA1::func1()" << endl; } virtual void vfunc1() { cout << "ClassA1::vfunc1()" << endl; } virtual void vfunc2() { cout << "ClassA1::vfunc2()" << endl; } private: int a1Data; }; class ClassA2 { public: ClassA2() { cout << "ClassA2::ClassA2()" << endl; } virtual ~ClassA2() { cout << "ClassA2::~ClassA2()" << endl; } void func1() { cout << "ClassA2::func1()" << endl; } virtual void vfunc1() { cout << "ClassA2::vfunc1()" << endl; } virtual void vfunc2() { cout << "ClassA2::vfunc2()" << endl; } virtual void vfunc4() { cout << "ClassA2::vfunc4()" << endl; } private: int a2Data; }; class ClassC : public ClassA1, public ClassA2 { public: ClassC() { cout << "ClassC::ClassC()" << endl; } virtual ~ClassC() { cout << "ClassC::~ClassC()" << endl; } void func1() { cout << "ClassC::func1()" << endl; } virtual void vfunc1() { cout << "ClassC::vfunc1()" << endl; } virtual void vfunc2() { cout << "ClassC::vfunc2()" << endl; } virtual void vfunc3() { cout << "ClassC::vfunc3()" << endl; } }; 

最后给出代码和结果

 ClassA1 *a1 = new ClassC; a1->func1(); // "ClassA1::func1()" 隐藏子类同名函数 a1->vfunc1(); // "ClassC::vfunc1()" 覆盖父类ClassA1虚函数 a1->vfunc2(); // "ClassC::vfunc2()" 覆盖父类ClassA1虚函数 没有a1->vfunc3(),父类没有这个虚函数 ClassA2 *a2 = new ClassC; a2->func1(); // "ClassA2::func1()" 隐藏子类同名函数 a2->vfunc1(); // "ClassC::vfunc1()" 覆盖父类ClassA2虚函数 a2->vfunc2(); // "ClassC::vfunc2()" 覆盖父类ClassA2虚函数 a2->vfunc4(); // "ClassA2::vfunc4()" 未被子类重写的父类虚函数 ClassC *c = new ClassC; c->func1(); // "ClassC::func1()" c->vfunc1(); // "ClassC::vfunc1()" c->vfunc2(); // "ClassC::vfunc2()" c->vfunc3(); // "ClassC::vfunc3()" c->vfunc4(); // "ClassA2::func4()" 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/202003.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月20日 上午8:06
下一篇 2026年3月20日 上午8:06


相关推荐

  • 国外推荐:计算机专业人士必读的书籍_计算机专业排名世界

    国外推荐:计算机专业人士必读的书籍_计算机专业排名世界国外大牛推荐:计算机专业人士必读好书(30本经典)分类:程序人生2014-04-1123:17175人阅读评论(0)收藏举报计算机书籍1.《代码大全》史蒂夫·迈克康奈尔  推荐数:1684  “优秀的编程实践的百科全书,《代码大全》注重个人技术,其中所有东西加起来,就是我们本能所说的“编写整洁的代码”。这本书有50

    2026年4月13日
    3
  • 轻量级过程改进之综述「建议收藏」

    轻量级过程改进之综述

    2022年1月26日
    47
  • cv::imread读不出图片的解决办法「建议收藏」

    cv::imread读不出图片的解决办法「建议收藏」imread()函数无法读取图片的原因测试程序:intmain(){ //读入一张图片 Matimg=imread("longmao.jpg"); if(img.empty()) { cout&lt;&lt;"Can’treadimage"&lt;&lt;endl; return-1; } //创建一个名为“龙猫”窗口 namedWindow("longmao"); …

    2022年10月10日
    5
  • java系统类加载器_网易js加载器下载地址

    java系统类加载器_网易js加载器下载地址http://www.cnblogs.com/szlbm/p/5504631.html为什么要自定义类加载器类加载机制:http://www.cnblogs.com/xrq730/p/4844915.html类加载器:http://www.cnblogs.com/xrq730/p/4845144.html这两篇文章已经详细讲解了类加载机制和类加载器,还剩最后一个

    2025年9月19日
    6
  • SpringBoot+MyBatisPlus+Thymeleaf+AdminLTE增删改查实战

    SpringBoot+MyBatisPlus+Thymeleaf+AdminLTE增删改查实战说明AdminLTE是网络上比较流行的一款Bootstrap模板,包含丰富的样式、组件和插件,非常适用于后端开发人员做后台管理系统。因为最近又做了个后台管理系统,这次就选的是AdminLTE做主题模板发现效果不错,这里我把最核心的SpringBoot如何集成AdminLTE实现增删改查的源码提供出来,需要的朋友可以参考而少走弯路。实现效果技术选型前端:Thymeleaf+Bootstrap+AdminLTE+插件后端:SpringBoot2.0+Mybatis-Plus数据库:

    2022年7月27日
    15
  • 欧拉角pitch、yaw,roll的理解_彻底搞懂四元数

    欧拉角pitch、yaw,roll的理解_彻底搞懂四元数目录0、简介一、四元数的定义二、欧拉角到四元数的转换2.1公式:2.2code:三、四元数到欧拉角的转换3.1公式3.2code:3.3四元素到旋转矩阵转换四.奇点五.矢量旋转证明:六.其他参考0、简介四元数与欧拉角之间的转换百度百科四元素在3D图形学中,最常用的旋转表示方法便是四元数和欧拉角,比起矩阵来具……

    2026年2月13日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号