C++对象的内存分布和虚函数表
c++中一个类中无非有四种成员:静态数据成员和非静态数据成员,静态函数和非静态函数。
1.非静态数据成员被放在每一个对象体内作为对象专有的数据成员。
2.静态数据成员被提取出来放在程序的静态数据区内,为该类所有对象共享,因此只存在一份。
3.静态和非静态成员函数最终都被提取出来放在程序的代码段中并为该类所有对象共享,因此每一个成员函数也只能存在一份代码实体。在c++中类的成员函数都是保存在静态存储区中的 ,那静态函数也是保存在静态存储区中的,他们都是在类中保存同一个惫份。
因此,构成对象本身的只有数据,任何成员函数都不隶属于任何一个对象,非静态成员函数与对象的关系就是绑定,绑定的中介就是this指针。成员函数为该类所有对象共享,不仅是处于简化语言实现、节省存储的目的,而且是为了使同类对象有一致的行为。同类对象的行为虽然一致,但是操作不同的数据成员。
#include"iostream.h"
class A
{
private:
int x;
int y;
public:
void sety()
{
y=;
}
void print()
{
cout<<"x="<<x<<endl<<"y="<<y<<endl;
}
};
void main()
{
A a;
a.sety();
a.print();
int *p=(int *)&a;//对象a的内存模型里面,只有非静态数据成员,所以是合理的。
*p=;
a.print();
}
4.单继承的对象的内存布局,第一个为虚函数表指针vtbl,其后为成员且先基类后子类,虚函数表里包含了所有的虚函数的地址,以NULL结束。虚函数如果子类有重写,就由子类的重新的代替。
<一>上述类图的解释:B的v2覆盖了A的v2,C的v1覆盖了A的v1,C的v3覆盖了B的v3.
注意:发生覆盖的特征有:
1) 不同的范围(分别位于派生类与基类);
2) 函数名字相同;
3) 参数相同;
4) 基类函数必须有virtual关键字。
成员函数被重载的特征
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
<二>类C的对象的内存模型为:
单继承的对象的布局,第一个为虚函数表指针vtbl,其后为成员且先基类后子类,虚函数表里包含了所有的虚函数的地址,以NULL结束。虚函数如果子类有重写,就由子类的重新的代替。
5.与单继承相同的是所有的虚函数都包含在虚函数表中,所不同的多重继承有多个虚函数表,当子类对父类的虚函数有重写时,子类的函数替换父类的函数在对应的虚函数位置,当子类有新的虚函数时,这些虚函数被加在第一个虚函数表的后面。
<一>对类图的解释:D的v3覆盖了B3的v3,另外D有一个新的虚函数vD。
<二>class D 的内存模型
总结:与单继承相同的是所有的虚函数都包含在虚函数表中,所不同的多重继承有多个虚函数表,当子类对父类的虚函数有重写时,子类的函数覆盖父类的函数在对应的虚函数位置,当子类有新的虚函数时,这些虚函数被加在第一个虚函数表的后面
6.虚继承,使公共的基类在子类中只有一份,我们看到虚继承在多重继承的基础上多了vbtable来存储到公共基类的偏移。
<一>类图的解释:D2覆盖了B的vB,GD覆盖了D1的vD1同时也覆盖B的vB,GD也有自己的虚函数vGD。
<二> class GD的内存模型
总结:虚继承,使公共的基类在子类中只有一份,我们看到虚继承在多重继承的基础上多了vbtable来存储到公共基类的偏移
C++对象的内存分布和虚函数表的更多相关文章
- C++对象的内存布局以及虚函数表和虚基表
C++对象的内存布局以及虚函数表和虚基表 本文为整理文章, 参考: http://blog.csdn.net/haoel/article/details/3081328 http://blog.csd ...
- C++对象内存分布详解(包括字节对齐和虚函数表)
转自:https://www.jb51.net/article/101122.htm 1.C++对象的内存分布和虚函数表: C++对象的内存分布和虚函数表注意,对象中保存的是虚函数表指针,而不是虚函数 ...
- c++内存分布之虚函数(单一继承)
系列 c++内存分布之虚函数(单一继承) [本文] c++内存分布之虚函数(多继承) 结论 1.虚函数表指针 和 虚函数表 1.1 影响虚函数表指针个数的因素只和派生类的父类个数有关.多一个父类,派生 ...
- C++中的虚函数以及虚函数表
一.虚函数的定义 被virtual关键字修饰的成员函数,目的是为了实现多态 ps: 关于多态[接口和实现分离,父类指针指向子类的实例,然后通过父类指针调用子类的成员函数,这样可以让父类指针拥有多种形态 ...
- C++ 类中有虚函数(虚函数表)时 内存分布
虚函数表 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的.简称为V-Table.在这个表中,主是要一个类的虚函数的地址表 ...
- c++类对象的内存分布
要想知道c++类对象的内存布局, 可以有多种方式,比如: 1)输出成员变量的偏移, 通过offsetof宏来得到 2)通过调试器查看, 比如常用的VS 1.没有数据成员的对象 class A{ }; ...
- vs查看虚函数表和类内存布局
虚继承和虚基类 虚继承:在继承定义中包含了virtual关键字的继承关系: 虚基类:在虚继承体系中的通过virtual继承而来的基类,需要注意的是:class CSubClass : publ ...
- C++虚函数表和对象存储
C++虚函数表和对象存储 C++中的虚函数实现了多态的机制,也就是用父类型指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数,这种技术可以让父类的指针有"多种形态",这 ...
- C++ 虚函数表与多态 —— 虚函数表的内存布局
C++面试经常会被问的问题就是多态原理.如果对C++面向对象本质理解不是特别好,问到这里就会崩. 下面从基本到原理,详细说说多态的实现:虚函数 & 虚函数表. 1. 多态的本质: 形 ...
随机推荐
- JS 验证字符串是否为空
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- vue watch 可以监听子组件props里面属性的改变
子组件watch 可以监听其props里面属性的改变 当changeFather导致calm改变时,会执行console.log('props change');
- Html 页面载入内容前,显示 loading 效果。
Html 内容 loading部分: <div id="sys-loading" class=""><div class="spin ...
- Excel技巧--按内容分列与合并
上表的A列,如果想要按横线分隔开多列,复制粘贴很麻烦,可以使用“数据”-->“分列”来分隔开: 1.选择A列,在A列后预先插入三列空列.点击“数据”—>“分列”,对话框选择按“分隔符号”分 ...
- 问题 Windows7VMware14安装虚拟机时出现 此主机不支持虚拟化实际模式。需要具备 Intel“VMX 不受限客户机”功能才能在 Intel 处理器上运行此虚拟机。 模块“CPUIDEarly”启动失败。
问题 Windows7VMware14安装虚拟机时出现 此主机不支持虚拟化实际模式.需要具备 Intel“VMX 不受限客户机”功能才能在 Intel 处理器上运行此虚拟机. 模块“CPUIDEarl ...
- 【转载】robocopy的用法
经常进行文件管理操作的朋友们,不满意于Windows系统内置的复制功能,因为它太龟速了.于是大家就使用FastCopy.TeraCopy之类的软件来加速复制,但是你是否知道Windows 7已经内置快 ...
- ORACLE procedure 一个参数分解成多个字符一点建议
测试时给什么变量就会生成什么变量, 但是在PROCEDURE时,你给的变量就会变成去掉包含字符q'/ /' 使用procedure splice添加字符串结果,是不包含q'/.删除时用的riqi赋值语 ...
- python:数据类型dict
一.字典 key -->value 储存大量数据,而且是关系型数据,查询速度非常快 数据类型分类: 可变数据类型:list , dict, set 不可变的数据类型:int , bool, st ...
- Redis为什么可以支持那么大的并发访问量?为什么redis没有单点并发瓶颈?
一是redis使用内存 而是redis使用多路复用的IO模型: 现代的UNIX操作系统提供了select/poll/kqueue/epoll这样的系统调用,这些系统调用的功能是:你告知我一批套接字,当 ...
- Android 梯形进度条、下载进度条;
额,Gif有点卡: 梯形.矩形.圆角.背景色.前景色.进度条中的文字都可以改: <?xml version="1.0" encoding="utf-8"? ...