c++内存分布之纯虚函数
关于
- 本文演示环境:VS2017+32位程序。
- 纯虚函数是一种特殊的虚函数。可以预测到:虚函数的结论同样适用纯虚函数,但是纯虚函数是一种特殊的存在,还是看看实际结果。
- 代码写的不够规范: 因为任何带虚函数的类的析构函数都应该是虚析构函数。但是我这里没有写出来,目的是缩短文章篇幅。
结论
1.虚函数表指针 和 虚函数表
- 1.1 影响虚函数表指针个数的因素只和派生类的父类个数有关。多一个父类,派生类就多一个虚函数表指针,同时,派生类的虚函数表就额外增加一个
- 1.2 派生类和父类同时含有虚函数,派生类的虚函数按照父类声明的顺序(从左往右),存放在继承的第一个父类中虚函数表后面,而不是单独再额外建立一张虚函数表
- 1.3 按照
先声明、先存储、先父类、再子类的顺序存放类的成员变量 - 1.4 无论是派生类还是父类,当出现了虚函数(普通虚函数、虚析构函数、纯虚函数),排在内存布局最前面的一定是虚函数表指针
2.覆盖继承
其实,覆盖继承不够准确。
2.1 成员变量覆盖
- 派生类和父类出现了同名的成员变量时,派生类仅仅将父类的同名成员隐藏了,而非覆盖替换
- 派生类调用成员变量时,按照就近原则,调用自身的同名变量,解决了当调用同名变量时出现的二义性的现象
2.2 成员函数覆盖
需要考虑是否有虚函数的情况
存在虚函数的覆盖继承
父类和派生类出现了同名虚函数函数((普通虚函数、纯虚函数),派生类的虚函数表中将子类的同名虚函数的地址替换为自身的同名虚函数的地址-------多态出现
不存在虚函数的覆盖继承
父类和派生类同时出现同名成员函数,这与成员变量覆盖继承的情况是一样的,派生类屏蔽父类的同名函数
1.单一继承
1.1 基类仅含有一个纯虚函数
1.1.1 代码
class baseD
{
public:
virtual void jumping() = 0;
int _mz = 100;
};
// 派生类
class deriveA : public baseD
{
public:
int _me = 3;
int _mf = 4;
};
1.1.2 内存分布
1>class deriveA size(16):
1> +---
1> 0 | +--- (base class baseD)
1> 0 | | {vfptr}
1> 4 | | _mz
1> | +---
1> 8 | _me
1>12 | _mf
1> +---
1>
1>deriveA::$vftable@:
1> | &deriveA_meta
1> | 0
1> 0 | &baseD::jumping
- 果然,与单一继承中基类只有一个虚函数的情况是完全一致的。
1.2 基类增加到2个纯虚函数
1.2.1 代码
class baseD
{
public:
virtual void jumping() = 0;
virtual void turning() = 0;
int _mz = 100;
};
// 派生类
class deriveA : public baseD
{
public:
int _me = 3;
int _mf = 4;
};
1.2.2 内存分布
1>class deriveA size(16):
1> +---
1> 0 | +--- (base class baseD)
1> 0 | | {vfptr}
1> 4 | | _mz
1> | +---
1> 8 | _me
1>12 | _mf
1> +---
1>
1>deriveA::$vftable@:
1> | &deriveA_meta
1> | 0
1> 0 | &baseD::jumping
1> 1 | &baseD::turning
- 分布情况与上面1.1中内存分布一致。
c++内存分布之纯虚函数的更多相关文章
- c++ 虚函数和纯虚函数
在你设计一个基类的时候,如果发现一个函数需要在派生类里有不同的表现,那么它就应该是虚的.从设计的角度讲,出现在基类中的虚函数是接口,出现在派生类中的虚函数是接口的具体实现.通过这样的方法,就可以将对象 ...
- C++ - 虚基类、虚函数与纯虚函数
虚基类 在说明其作用前先看一段代码 class A{public: int iValue;}; class B:public A{public: void bPrintf(){ ...
- c++虚函数,纯虚函数,抽象类,覆盖,重载,隐藏
C++虚函数表解析(转) ——写的真不错,忍不住转了 http://blog.csdn.net/hairetz/article/details/4137000 浅谈C++多态性 http://bl ...
- C++纯虚函数
本文较为深入的分析了C++中虚函数与纯虚函数的用法,对于学习和掌握面向对象程序设计来说是至关重要的.具体内容如下: 首先,面向对象程序设计(object-oriented programming)的核 ...
- C++学习25 纯虚函数和抽象类
在C++中,可以将成员函数声明为纯虚函数,语法格式为: ; 纯虚函数没有函数体,只有函数声明,在虚函数声明结尾加上=0,表明此函数为纯虚函数. 最后的=0并不表示函数返回值为0,它只起形式上的作用,告 ...
- 从零开始学C++之虚函数与多态(二):纯虚函数、抽象类、虚析构函数
一.纯虚函数 虚函数是实现多态性的前提 需要在基类中定义共同的接口 接口要定义为虚函数 如果基类的接口没办法实现怎么办? 如形状类Shape 解决方法 将这些接口定义为纯虚函数 在基类中不能给出有意义 ...
- C++ Primer--虚函数与纯虚函数的区别
首先:强调一个概念 定义一个函数为虚函数,不代表函数为不被实现的函数. 定义他为虚函数是为了允许用基类的指针来调用子类的这个函数. 定义一个函数为纯虚函数,才代表函数没有被实现. 定义纯虚函数是为了实 ...
- c++,纯虚函数与抽象类
1.纯虚函数的定义: (1)虚函数被“初始化”为0的函数.声明纯虚函数的一般形式是virtual 函数类型 函数名(参数表列) =0;(2)纯虚函数没有函数体:(3)最后面的“=0”并不表示函数返回值 ...
- c++中虚函数和纯虚函数定义
只有用virtual声明类的成员函数,使之成为虚函数,不能将类外的普通函数声明为虚函数.因为虚函数的作用是允许在派生类中对基类的虚函数重新定义.所以虚函数只能用于类的继承层次结构中. 一个成员函数被声 ...
随机推荐
- DirectX12 3D 游戏开发与实战第九章内容(上)
仅供个人学习使用,请勿转载. 9.纹理贴图 学习目标: 学习如何将局部纹理映射到网格三角形上 探究如何创建和启用纹理 学会如何通过纹理过滤来创建更加平滑的图像 探索如何使用寻址模式来进行多次纹理贴图 ...
- linux中conda升级R到4.0?
目录 前言 问题 曲线救国 前言 虽然我的win版本R已经用4了,但之前在Linux环境一直没用R4.0,因为Linux涉及的东西太多,担心不稳定,牵一发而动全身. 但现在有好些R包必须要用更新到R4 ...
- 36-Same Tree
Same Tree My Submissions QuestionEditorial Solution Total Accepted: 126116 Total Submissions: 291884 ...
- MySQL深层理解,执行流程
MySQL是一个关系型数据库,关联的数据保存在不同的表中,增加了数据操作的灵活性. 执行流程 MySQL是一个单进程服务,每一个请求用线程来响应, 流程: 1,客户请求,服务器开辟一个线程响应用户. ...
- 详解 Rainbond Ingress 泛解析域名机制
Rainbond 作为一款云原生应用管理平台,天生带有引导南北向网络流量的分布式网关 rbd-gateway.区别于一般的 Ingress 配置中,用户需要自行定义域名的使用体验,Rainbond 的 ...
- 振鹏同学正式学习java的第一天!
一.今日收获 1.最棒的莫过于运行Java的HelloWorld! 2.在同学的帮助下历经坎坷困苦安装完成了Eclipse软件并设置好环境变量. 3.最最最开始了解了Java的前世今生,编程语言发展的 ...
- 【Go语言学习笔记】包
包其实是每个大型工程都会使用的模块化工具. 将相关的代码封装成一个包,给其他项目调用,提供不同的功能. GO的设计是将一个文件夹看成一个包,虽然不一定非要用文件夹的名字,但是比较建议. 同一个文件夹下 ...
- C++字节对齐(对象大小)
内部数据成员对齐参考这篇 https://www.cnblogs.com/area-h-p/p/10316128.html 这里只强调C++字节对齐特点 ①静态数据成员属于类域,在对象中不占大小 ②若 ...
- Postman 中 Pre-request Script 常用 js 脚本
1. 生成一个MD5或SHA1加密的字符串str_md5,str_sha1 string1 = "123456"; var str_md5= CryptoJS.MD5(string ...
- mysql 5.7 压缩包安装教程
前言 : 避免之前装的MySQL影响 首先进入dos窗口执行 sc delete mysql 删除已有的mysql服务 (一) 下载MySQL5.7 版本压缩包 网址 https://de ...