热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c++_4:多态_2_虚函数的原理

上下类型转换与晚绑定classMammal{public:virtualspeak();move();};ClassDog:publicMammal{voidspeak(

上下类型转换与晚绑定

class Mammal
{public:virtual speak();move();
};
Class Dog : public Mammal
{void speak();void move();
};int main()
{Mammal *pDog=new Dog;pDog->Move(); // 调用Mammal的方法---Mammal::move//向上类型转换pDog->speak(); //调用Dog的方法---Dog::speak---虚函数
}

虚函数表

转载博客: http://blog.csdn.net/haoel/article/details/1948051/


  • 父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数
  • C++的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置

class Base {public:virtual void f() { cout <<"Base::f" <virtual void g() { cout <<"Base::g" <virtual void h() { cout <<"Base::h" <

这里写图片描述


  • 函数表的最后多加了一个结点&#xff0c;这是虚函数表的结束结点&#xff0c;就像字符串的结束符“/0”一样
  • 而在Ubuntu 7.10 &#43; Linux 2.6.22 &#43; GCC 4.1.3下&#xff0c;这个值是如果1&#xff0c;表示还有下一个虚函数表&#xff0c;如果值是0&#xff0c;表示是最后一个虚函数表。

无继承的虚函数表

这里写图片描述


  • 在这个继承关系中&#xff0c;子类没有重载任何父类的函数。那么&#xff0c;在派生类的实例中&#xff0c;其虚函数表如下所示&#xff1a;

这里写图片描述


  • 虚函数按照其声明顺序放于表中。
  • 父类的虚函数在子类的虚函数前面。’

一般继承&#xff08;有虚函数覆盖&#xff09;

这里写图片描述

这里写图片描述


  • 覆盖的f()函数被放到了虚表中原来父类虚函数的位置。
  • 没有被覆盖的函数依旧。

Base *b &#61; new Derive();b->f(); //调用Derive::f()

  • b所指的内存中的虚函数表的f()的位置已经被Derive::f()函数地址所取代&#xff0c;于是在实际调用发生时&#xff0c;是Derive::f()被调用了。这就实现了多态。

多重继承&#xff08;无虚函数覆盖&#xff09;

这里写图片描述

这里写图片描述


  • 每个父类都有自己的虚表。
  • 子类的成员函数被放到了第一个父类的表中。&#xff08;所谓的第一个父类是按照声明顺序来判断的&#xff09;
  • 这样做就是为了解决不同的父类类型的指针指向同一个子类实例&#xff0c;而能够调用到实际的函数。

多重继承&#xff08;有虚函数覆盖&#xff09;

这里写图片描述

这里写图片描述


  • 三个父类虚函数表中的f()的位置被替换成了子类的函数指针。

注意


  • 不可通过父类型的指针访问子类自己的虚函数

Base1 *b1 &#61; new Derive();b1->f1(); //编译出错

  • 任何妄图使用父类指针想调用子类中的未覆盖父类的成员函数的行为都会被编译器视为非法&#xff0c;所以&#xff0c;这样的程序根本无法编译通过。但在运行时&#xff0c;我们可以通过指针的方式访问虚函数表来达到违反C&#43;&#43;语义的行为。&#xff08;关于这方面的尝试&#xff0c;通过阅读后面附录的代码&#xff0c;相信你可以做到这一点&#xff09;



推荐阅读
  • 远程访问用户 Kindle通过电子书实现控制
    介绍自2007年以来,亚马逊已售出数千万台Kindle,令人印象深刻。但这也意味着数以千万计的人可能会因为这些Kindle中的软件漏洞而被黑客入侵。他 ... [详细]
  • Linux环境下的PHP7安装与配置指南
    本文详细介绍了如何在Linux操作系统中安装和配置PHP7,包括检查当前PHP版本、升级PHP以及配置MySQL支持等步骤,适合后端开发者参考。 ... [详细]
  • 我们正在使用GNU Make来构建我们的系统,在makefile文件的末尾,我们通过一个名为Makedepends的包含来生成一系列的.d文件。然而,当文件被删除或移动时,依赖关系会中断,我们需要寻找一种方法来优雅地处理这种情况。 ... [详细]
  • PHP 5.4.8 编译安装指南
    本文详细介绍了如何在Linux环境下编译安装PHP 5.4.8,并配置为FastCGI模式运行。包括所需依赖包的安装、源代码下载、编译配置及启动服务等步骤。 ... [详细]
  • 本文介绍了如何在ARM架构的裸机环境中通过C语言编程点亮LED灯。主要包括初始化栈指针、关闭看门狗以及编写控制LED灯状态的C代码等关键步骤。 ... [详细]
  • 尽管在WPF中工作了一段时间,但在菜单控件的样式设置上遇到了一些基础问题,特别是关于如何正确配置前景色和背景色。 ... [详细]
  • 本文探讨了C语言中关于函数定义与调用的一些基本规则,特别是解释了为何函数定义不可嵌套,而函数调用却可以嵌套,并通过具体示例加以说明。 ... [详细]
  • 正在学习操作系统开发,遇到一个内核在GRUB Legacy(0.97)中无法成功引导的问题。具体表现为输入内核命令后显示错误信息,尝试引导时GRUB挂起。 ... [详细]
  • 本文提供了一个Android应用中用于抓取网页信息并下载图片的示例代码。通过该代码,开发者可以轻松实现从指定URL获取网页内容及其中的图片资源。 ... [详细]
  • 本文探讨了 Rust 编程语言中 'eq()' 方法与 '==' 运算符之间的差异,并通过示例说明了它们在不同类型比较时的行为。 ... [详细]
  • 深入理解Java类加载机制及安全防护
    本文探讨了Java类加载的过程,包括加载、验证、准备、解析和初始化五个阶段,并详细解释了每个阶段的具体操作和意义。此外,文章还讨论了Java如何通过双亲委派模型来保障核心API的安全性,以及在特定情况下如何打破这一机制。 ... [详细]
  • Qt应用开发:创建基本窗口
    本文介绍如何使用Qt框架创建基础窗口的两种方法。第一种方法直接在main函数中创建并显示窗口;第二种方法通过定义一个继承自QWidget的类来实现更复杂的功能。 ... [详细]
  • 为什么会崩溃? ... [详细]
  • 本文介绍了如何通过创建自定义 XML 文件来修改 Android 中 Spinner 的项样式,包括颜色和大小的调整。 ... [详细]
  • 我在尝试将组合框转换为具有自动完成功能时遇到了一个问题,即页面上的列表框也被转换成了自动完成下拉框,而不是保持原有的多选列表框形式。 ... [详细]
author-avatar
mobiledu2502861133
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有