从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响
首先重新回顾一下关于类/对象大小的计算原则:
第一个数据成员放在offset为0的位置
其它成员对齐至min(sizeof(member),#pragma pack(n)所指定的值)的整数倍。
整个结构体也要对齐,结构体总大小对齐至各个成员中最大对齐数的整数倍。
类的大小与数据成员有关与成员函数无关
类的大小与静态数据成员无关
虚继承对类的大小的影响
虚函数对类的大小的影响
下面通过实例来展示虚继承和虚函数对类大小造成的影响。
测试环境为:Win32 + Vs2008
一、只出现虚继承的情况
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#include <iostream>
using namespace std; class BB class B1 : class B2 : class DD : int main ( B1 b1 ; cout<<&b1 <<endl; p = ( DD dd ; BB* pp ; pp = &dd ; return |
从输出的地址和虚基类表成员数据可以画出对象内存模型图:
virtual base table
本类地址与虚基类表指针地址的差
虚基类地址与虚基类表指针地址的差
virtual base table pointer(vbptr)
从程序可以看出pp是BB* 指针,pp首先指向dd内存,当执行pp->bb_时,先找到首个vbptr,找到虚基类BB地址与虚基类表指针地址的差,也即是20,接着pp偏移20个字节指向了dd对象中的BB部分,然后就访问到了bb_,这是在运行时才做的转换。
二、只出现虚函数的情况
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#include <iostream>
using namespace std; class Base virtual class Derived : typedef int main ( Derived d ; return |
从输出的函数体可以画出对象内存模型图:
vtbl:虚函数表(存放虚函数的函数指针)
vptr:虚函数表指针
从输出可以看出,Derived类继承了Base::Fun1,而覆盖了Fun2,此外还有自己的Fun3。注意,因为Fun3是虚函数,才会出现在虚函数表,如果是一般函数是不会的,因为不用通过vptr间接访问。
三、虚继承与虚函数同时出现的情况:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
#include <iostream>
using namespace std; class BB class B1 : class B2 : class DD : typedef int main ( BB bb ; B1 b1 ; cout<<p [ DD dd ; return |
从输出的虚基类表成员数据和虚函数体可以画出对象内存模型图:
虚基类表和虚基类表指针的存在。
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范
从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响的更多相关文章
- c++虚继承与虚函数
学习继承与多态时看到这两个概念,记录整理. 虚继承与虚函数都是用virtual关键字实现,虚继承为了防止多重继承,而虚函数为了实现多态. 是几个例子. 虚继承: class A{}; class B: ...
- C++多重继承分析——《虚继承实现原理(虚继承和虚函数)》
博客转载:https://blog.csdn.net/longlovefilm/article/details/80558879 一.虚继承和虚函数概念区分 虚继承和虚函数是完全无相关的两个概念. 虚 ...
- C++对象内存模型2 (虚函数,虚指针,虚函数表)
从例子入手,考察如下带有虚函数的类的对象内存模型: class A { public: virtual void vfunc1(); virtual void vfunc2(); void func1 ...
- C++虚函数、虚继承、对象内存模型(转)
参考:http://blog.csdn.net/hxz_qlh/article/details/14633361 需要注意的是虚继承.多重继承时类的大小.
- C++基础 (6) 第六天 继承 虚函数 虚继承 多态 虚函数
继承是一种耦合度很强的关系 和父类代码很多都重复的 2 继承的概念 3 继承的概念和推演 语法: class 派生类:访问修饰符 基类 代码: … … 4 继承方式与访问控制权限 相对的说法: 爹派生 ...
- C++对象内存模型2 (虚函数,虚指针,虚函数表)(转)
class A { public: virtual void vfunc1(); virtual void vfunc2(); void func1(); void func2(); virtual ...
- 从零开始学 Web 之 JavaScript(三)函数
大家好,这里是「 Daotin的梦呓 」从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」公众号,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识 ...
- C++学习笔记----4.5 C++继承时的对象内存模型
推荐阅读:http://blog.csdn.net/randyjiawenjie/article/details/6693337 最近研究了一下,C++继承的内存对象模型.主要是读了读http://b ...
- 记录:C++类内存分布(虚继承与虚函数)
工具:VS2013 先说一下VS环境下查看类内存分布的方法: 先选择左侧的C/C++->命令行,然后在其他选项这里写上/d1 reportAllClassLayout,它可以看到所有相关类的内存 ...
随机推荐
- PHP时间戳与时间相互转换(精确到毫秒)
原文:PHP时间戳与时间相互转换(精确到毫秒) /** 获取当前时间戳,精确到毫秒 */ function microtime_float(){ list($usec, $sec) = explo ...
- Hibernat之关系的处理多对多
第一步:编写两个pojo,比如一个学生表一个课程表 这里使用注解. 需要 课程表: package com.qcf.pox; import java.util.HashSet; import jav ...
- ASP.NET如何显示农历时间
ASP.NET如何显示农历时间 CS部分代码如下: 代码如下: public string ChineseTimeNow = ""; public string ForignTi ...
- JSP之项目路径问题(${pageContext.request.contextPath},<%=request.getContextPath()%>以及绝对路径获取)
本随笔这是作为一个记录使用,以备后查.项目完成之后本地部署OK,本地Linux部署OK,都可以正常的访问,可是当我把它部署到服务器上面的时候,首页可以正常访问,可是当发出请求的时候却报错误了,说找不到 ...
- CodeIgniter学习一:基础知识
1. url片段(CI域名组成说明) example.com/index.php/test/index 第一部分(test):控制器 第二部分(index):方法,动作 如果第二部分 ...
- VS SQL 出现%CommonDir%dte80a.olb 该解决方案
VS SQL 出现%CommonDir%dte80a.olb 该解决方案 在网上搜索解决方法的时候.别人就说你从别的电脑复制一个到C:\Program Files\Common Files\mic ...
- Java设置环境变量
客上转过来的. 非常多人写了非常久java代码.还不知道环境变量是怎么一回事.科普一下. 一.java设置环境变量 - 精简版 1.右键打开我的电脑->属性->高级->环境变量 ...
- leetcode[88] Gray Code
题目:格雷码. 格雷码是从0开始且之后两个相邻码之间只有一个符号不相同,例如000,100,101,111三个相邻之间只有一个二进制不同. 现在给定一个数字n,然后给出格雷码所对应的数字.例如: Fo ...
- struts2 <s: select 标签值
JSP页面: <s:select label="家长导航" value="id" name="navson.pid" list=&q ...
- Plan : 破晓
题记 : 不要因为走的太远而忘记自己为什么而出发. 1. 白书(算法竞赛入门经典)看完(每一句话都要读懂) 2. 每次听完课把当天内容复习完(自习室10点以后复习) 3. 微机实验要提前预习(把实验报 ...