c++ 之 内存模型:虚函数篇

一、虚函数

1.虚函数表位置分析

类:有虚函数,这个类会产生一个虚函数表

类的对象:有一个指针(vptr)会指向类的虚函数表——虚函数表指针。(位置可能在类内存空间的开头,也可能在末尾,具体由编译器实现决定)

2.继承关系作用下虚函数的手工调用

拿到虚函数表的地址,通过定义函数指针并赋值的方式可以直接调用虚函数。子类的虚函数会覆盖父类的虚函数。

3.虚函数表分析

(1)一个类只有包含虚函数才会存在虚函数表,同属于一个类的对象共享虚函数表,但拥有各自的虚函数表指针(vptr)。当然所有的该类对象的vptr都指向同一个虚函数表。

(2)父类中有虚函数就等于子类中有虚函数。(父类中有虚函数表则子类中肯定有虚函数表) 因为子类会继承父类。

如果子类中将父类虚函数的virtual去掉,函数就不再是虚函数?

在父类中是虚函数,即使子类中该函数不写virtual,它依然是虚函数。

不管是父类还是子类,每一个类都只有属于自己的唯一虚函数表。子类中是否会存在多个虚函数表?

(3)如果子类中完全没有新的虚函数,则子类虚函数表的内容与父类虚函数表的内容相同。但两个虚函数表在内存中的位置是不同的。是两个虚函数表。虚函数表中的每一项包含一个虚函数的首地址,但如果子类的虚函数表某项和父类虚函数表某项代表同一个函数(这表示子类没有覆盖父类的虚函数)则该表项所指向的函数相同。

(4)超出虚函数表部分内容不可知。

(5)当子类对象为父类对象赋值时,子类中的属于父类的那一部分会被编译器自动区分(切割)出来并拷贝给父类对象;所以BaseClass base = derive;实际做了两件事:一、生成了一个base对象;二、用derive的部分值来对base对象进行了初始化。 (但此时编译器在处理base对象的虚函数表指针 值的时候,编译器会根据base的类型来自动决策为BaseClass 的虚函数表地址)

(4)OO(面向对象)和OB(基于对象)概念

C++是通过类的指针和引用来支持多态,这是一种程序设计风格,这就是我们常说的面向对象。object-oriented model

OB(object-base)也叫ADT抽象数据模型[abstract datatype model],不支持多态,执行速度更快。因为函数调用的解析不需要运行时决定(没有多态),比如Base *pbase = new Derive();Base &base2 = derive2;而是在编译期间完成,内存空间紧凑程度上更为紧凑,因为没有虚函数这些概念。

但OB(object-base)的设计灵活性上较差,C++既支持面向对象程序设计。也支持基于对象程序设计。

4.多重继承虚函数表分析

原文地址:https://www.cnblogs.com/sxgloverr1314/p/11410039.html

时间: 2024-10-12 21:15:24

c++ 之 内存模型:虚函数篇的相关文章

c++ 内存分配 虚函数实现多态等

看到了很好的解释,先mark下,有空整理. 虚函数实现多态与多重继承乌索普的回答 很有收获,毕竟我觉得多态才是面向对象的灵魂. 这样的设计也让人得以理解为什么虚函数会像成员变量一样与对象绑定. C++成员函数在内存中的存储方式 原文地址:https://www.cnblogs.com/zsl96/p/8732662.html

c++ 之 内存模型:对象篇

一.对象 1.类对象所占用的空间 (1)类的普通成员函数不占用类对象的成员空间 (2)一个类对象至少要占用1字节的内存空间 (3)类的普通成员变量占用类对象的空间(每一个类的对象拥有属于自己的成员变量) (4)类的普通成员函数虽然写在类的定义中,但普通成员函数不会占用类对象的内存空间 (5)所有类的对象公用一份成员函数 2.C++对象结构发展和演化 (1)非静态的成员变量跟着对象走(存在于对象内部)(每一个类的对象拥有属于自己的成员变量) (2)静态成员变量所占用的内存空间于类对象无关,所有类对

深入理解Java内存模型之系列篇[转]

原文链接:http://blog.csdn.net/ccit0519/article/details/11241403 深入理解Java内存模型(一)——基础 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递. see:命令式编程.函数式编程 在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存

JavaScript学习系列之内存模型篇

一个热爱技术的菜鸟...用点滴的积累铸就明日的达人 正文 如果真的想学好一门语言,那么一定要了解它内存模型,本篇文章就带你走进JavaScript的内存模型,由于本人才疏学浅,若有什么表述有误的地方,欢迎各位看官能够指点一二,在此不胜感激... 在阅读这边文章之前,默认您已经掌握了JavaScript的基本概念.栈堆等基本数据结构以及计算机基本理论基础,如有了解欠缺,请移步相关博客后再阅读本文. 一.基本的数据类型的内存结构 首先粗略的介绍一下JavaScript中五种基本的数据类型Undefi

(转)c#对象内存模型

对象内存模型 C#的对象内存模型写这篇博客的主要目的是为了加深自己的理解,如有不对的地方,请各位见谅. C#的对象内存模型: 一.栈内存和堆内存1.栈内存 由编译器自动分配和释放,主要用来保存一些局部变量.函数的参数等,例如,int a = 10 ,那么编译器会自动在栈上开辟一块内容用来存储变量a.2.堆内存 由程序员手动申请和释放,在C++中,通过new关键字申请,编译器不会释放,必须通过delete释放,对于C#,通过new 关键字申请,因为编译器的垃圾回收机制,程序员不需要手动释放内存.例

Cocos2d-x v3.11 中的新内存模型

Cocso2d-x v3.11 一项重点改进就是 JSB 新内存模型.这篇文章将专门介绍这项改进所带来的新研发体验和一些技术细节. 1. 成果 在 Cocos2d-x v3.11 之前的版本中,使用 JS 语言发布原生版本的用户可能多少都会遇到一个经典的问题:Invalid Native Object,或者遇到一些莫名其妙的 JS 对象失效的崩溃.而解决这些问题,我们给出的解决方案基本是使用 retain / release 来显式声明持有或释放对象,或者是在脚本层更合理得持有对象索引.而在 v

C++ 无虚函数的单继承内存模型

C++类因为有继承的存在要比C时代的struct复杂得一些,特别是加上有虚函数的时候,以及多继承等这些特性更是令其内存布局变得面目全非.说实在的我也把握不了,我只是在一个实际的平台上进行了一些探索而已,并用此篇笔记将我的探索成果记录下来. 虽然说有些东西在C++标准里面没有规定如何做,不同的实现可能会有不同的作法,但是了解一个实际的系统是如何做的也会有益于我们更加深入的了解C++或者举一反三地理解其他的实现,而且如果我们了解了自己所用的系统上的具体实现的话,就可以对其为所欲为. 没有虚函数单继承

c++对象内存模型之虚析构函数篇(1)

看了两篇关于c++对象内存模型的文章,来源在这里: http://blog.csdn.net/haoel/article/details/3081328/ http://blog.csdn.net/haoel/article/details/3081385 文章中讲了多种继承模式中虚函数的实际情况,按我的理解是把单一继承理解好了,其它几种只是一种变种.当然没这文章,我断想不到c++对象内存是这个样子. 文章中讲的情况,唯独没有讲有虚析构函数存在的情形.我学着文章中介绍的方法,用试探的方式找有虚析

C++对象内存模型2 (虚函数,虚指针,虚函数表)

从例子入手,考察如下带有虚函数的类的对象内存模型: 1 class A { 2 public: 3 virtual void vfunc1(); 4 virtual void vfunc2(); 5 void func1(); 6 void func2(); 7 virtual ~A(); 8 private: 9 int m_data1, m_data2; 10 }; 11 12 class B : A { 13 public: 14 virtual void vfunc1();; 15 vo