C++类的内存结构
简单类
class Base
{
int a;
int b;
public:
void CommonFunction();
};
简单类继承
class DerivedClass: public Base
{
int c;
public:
void DerivedCommonFunction();
};
带有虚函数的类
class Base
{
int a;
int b;
public:
void CommonFunction();
void virtual VirtualFunction();
};
虚函数类继承
没有复写的继承
class DerivedClass: public Base
{
int c;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
};
复写的继承
class DerivedClass1 : public Base
{
int c;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
void virtual VirtualFunction2();
};
多重继承
class Base
{
int a;
int b;
public:
void CommonFunction();
void virtual VirtualFunction();
};
class DerivedClass1: public Base
{
int c;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
};
class DerivedClass2 : public Base
{
int d;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
};
class DerivedDerivedClass : public DerivedClass1, public DerivedClass2
{
int e;
public:
void DerivedDerivedCommonFunction();
void virtual VirtualFunction();
};
内存分布从父类到子类,依次如下:
Base中有一个虚表指针
DerivedClass1继承了Base,内存排布是先父类后子类。
DerivedClass2的情况是类似于DerivedClass1的。
DerivedDerivedClass,由外向内看,它并列地排布着继承而来的两个父类DerivedClass1与DerivedClass2,还有自身的成员变量e。DerivedClass1包含了它的成员变量c,以及Base,Base有一个0地址偏移的虚表指针,然后是成员变量a和b;DerivedClass2的内存排布类似于DerivedClass1,注意到DerivedClass2里面竟然也有一份Base。
这里有两份虚表了,分别针对DerivedClass1与DerivedClass2,在&DerivedDericedClass_meta下方的数字是首地址偏移量,靠下面的虚表的那个-16表示指向这个虚表的虚指针的内存偏移,这正是DerivedClass2中的{vfptr}在DerivedDerivedClass的内存偏移。
虚继承
class DerivedClass1: virtual public Base
{
int c;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
};
class DerivedClass2 : virtual public Base
{
int d;
public:
void DerivedCommonFunction();
void virtual VirtualFunction();
};
class DerivedDerivedClass : public DerivedClass1, public DerivedClass2
{
int e;
public:
void DerivedDerivedCommonFunction();
void virtual VirtualFunction();
};
Base类没有变化
DerivedClass1就已经有变化了,原来是先排虚表指针与Base成员变量,vfptr位于0地址偏移处;但现在有两个虚表指针了,一个是vbptr,另一个是vfptr。vbptr是这个DerivedClass1对应的虚表指针,它指向DerivedClass1的虚表vbtable,另一个vfptr是虚基类表对应的虚指针,它指向vftable。
下面列出了两张虚表,第一张表是vbptr指向的表,8表示{vbptr}与{vfptr}的偏移;第二张表是vfptr指向的表,-8指明了这张表所对应的虚指针位于内存的偏移量。
DerivedClass2的内存分布类似于DerivedClass1,同样会有两个虚指针,分别指向两张虚表(第二张是虚基类表)。
下面来仔细看一下DerivedDerivedClass的内存分布,这里面有三个虚指针了,但base却只有一份。第一张虚表是内含DerivedClass1的,20表示它的虚指针{vbptr}离虚基表指针{vfptr}的距离,第二张虚表是内含DerivedClass2的,12表示它的虚指针{vbptr}离虚基表指针{vfptr}的距离,最后一张表是虚基表,-20指明了它对应的虚指针{vfptr}在内存中的偏移。
虚继承的作用是减少了对基类的重复,代价是增加了虚表指针的负担(更多的虚表指针)。
下面总结一下(当基类有虚函数时):
1. 每个类都有虚指针(vptr, virtual table pointer)和虚函数表(vtbl, virtual table);
2. 如果不是虚继承,那么子类将父类的虚指针继承下来,并指向自身的虚函数表(发生在对象构造时)。有多少个虚函数,虚函数表里面的项就会有多少。多重继承时,可能存在多个的基类虚函数表与虚指针;
3. 如果是虚继承,那么子类会有两份虚指针,一份指向自己的虚函数表,另一份指向基类虚函数表,多重继承时基类虚函数表与基类虚指针有且只有一份。
C++类的内存结构的更多相关文章
- Java内存结构、类的初始化、及对象构造过程
概述 网上关于该题目的文章已经很多,我觉得把它们几个关联起来讲可能更好理解一下.与其它语言一样,它在执行我们写的程序前要先分配内存空间,以便于存放代码.数据:程序的执行过程其实依然是代码的执行及数据的 ...
- C++类对应的内存结构
提示1:对“内存结构”表示有疑问或不解的,先参考: http://blog.csdn.net/guogangj/archive/2007/05/25/1625199.aspx, 本文使用的表示方法和V ...
- 关于结构体和C++类的内存地址问题
关于结构体和C++类的内存地址问题 今天终于有时间写点东西了~ 太爽了 *_* 很多人都知道C++类是由结构体发展得来的,所以他们的成员变量(C语言的结构体只有成员变量)的内存分配机制是一样 ...
- jvm系列(二):JVM内存结构
JVM内存结构 所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能 ...
- JVM之内存结构
JVM是按照运行时数据的存储结构来划分内存结构的.JVM在运行Java程序时,将他们划分成不同格式的数据,分别存储在不同的区域,这些数据就是运行时数据.运行时数据区域包括堆,方法区,运行时常量池,程序 ...
- Oracle之内存结构(SGA、PGA)
一.内存结构 SGA(System Global Area):由所有服务进程和后台进程共享: PGA(Program Global Area):由每个服务进程.后台进程专有:每个进程都有一个PGA. ...
- 浅析JVM内存结构和6大区域(转)举例非常好
内存作为系统中重要的资源,对于系统稳定运行和高效运行起到了关键的作用,Java和C之类的语言不同,不需要开发人员来分配内存和回收内存,而是由JVM来管理对象内存的分配以及对象内存的回收(又称为垃圾回收 ...
- [转]oracle学习入门系列之五内存结构、数据库结构、进程
原文地址:http://www.2cto.com/database/201505/399285.html 1 Oracle数据库结构 关于这个话题,网上一搜绝对一大把,更别提书籍上出现的了,还有很多大 ...
- 虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte
#include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout < ...
随机推荐
- ORCFILE IN HDP 2: BETTER COMPRESSION, BETTER PERFORMANCE
ORCFILE IN HDP 2: BETTER COMPRESSION, BETTER PERFORMANCE by Carter Shanklin The upcoming Hive 0.12 ...
- vue项目,ie11 浏览器报 Promise 未定义的错误
报错: {description: "“Promise”未定义", message: "“Promise”未定义", name: "Referenc ...
- centos6.5下配置django+uwsgi+nginx
https://blog.csdn.net/huanbia/article/details/54630180
- centos7下安装docker(18docker日志---docker logs)
在微服务架构中,由于容器的数量众多以及快速变化的特性使得记录日志和监控变得越来越重要,考虑到容器的短暂和不固定周期,当我们需要排查问题的时候容器可能不在了.因此,一套集中式的日志管理系统是生产环境中不 ...
- Python requests上传文件demo
#!/usr/bin/env python # -*- coding: utf-8 -*- import requests headers = {'uuid': '5cb572b7-c0a7-4d90 ...
- Bean named '*' must be of type [*], but was actually of type []
本地Service 名字和调用别的maven项目Service重名
- 阿里云配置tomcat https
阿里云申请免费的SSL证书和配置https,可参考该篇博文:https://blog.csdn.net/baidu_19473529/article/details/70037976 虽然有现成的,不 ...
- ArrayList中ConcurrentModificationException
java中两种基本的集合结构ArrayList和LinkedList底层有两种不同的存储方式实现,ArrayList为数组实现,属于顺序存储,LinkedList为链表实现,属于链式存储,在对Arra ...
- 用ASP.NET MVC仿站糗事百科
废话就不多说,直接来操作,有些细节问题就不一一解说了(没有几天几夜都说不完),主意是想让大家看完知道大概这个框架是怎么搭建的就可以了 一. 新建一个解决方案,搭建三层架构,分别为: DAL层 .DL ...
- oracle 删除表空间TABLESPACE步骤及注意项
告诉大家,我喜欢通过toad for oralce来实现对oracle数据库的操作. 1.首先通过数据库管理员用户以SYSDBA身份登录.比如使用sys用户去登录 2.查看和记录待删除表空间所在的物理 ...