c++ 基础知识回顾 继承 继承的本质就是数据的copy
c++ 基础知识笔记
继承
什么是继承 继承就是子类继承父类的成员属性以及方法
继承的本质就是 数据的复制 是编译器帮我们做了很多操作
class Base
{
public:
Base(){
cout << "Base 构造函数"<< endl;
}
~Base(){
cout << "Base 析构函数" << endl;
}
};
class Sub : public Base
{
public:
Sub(){
cout << "Sub 构造函数"<< endl;
}
~Sub(){
cout << "Sub 析构函数"<<endl;
}
};
void Test(){
Sub sub;
cout << sizeof(sub)<<endl;
}

这个时候我们打印出来的 Sub的大小是1
因为它没有任何数据
如果说我们这个时候在Base 和Sub类中各自增加两个int 类型的成员变量 我们再来看看Sub的大小
class Base
{
public:
Base(){
cout << "Base 构造函数"<< endl;
}
~Base(){
cout << "Base 析构函数" << endl;
}
private:
int x;
int y;
};
class Sub : public Base
{
public:
Sub(){
cout << "Sub 构造函数"<< endl;
}
~Sub(){
cout << "Sub 析构函数"<<endl;
}
public:
int a;
int b;
};
void Test(){
Sub sub;
cout << sizeof(sub)<<endl;
}

这个时候我们可以看到结果变成了16
为什么是 16呢 因为Base 与 Sub各自有两个int类型的成员变量 int 类型占用4个字节 所以Sub自己有两个int类型的变量 然后又继承了 Base的 所以这个时候的Sub大小就是 以Base为起始+Sub的大小所以就是16个字节
然后我们在构造函数中给这两个类的各自成员赋上初始值再观察下反汇编的代码


我们仔细看 编译器帮我们分配了 Sub类的临时内存
我们仔细看一下ECX 存储的就是 我们定义的Sub类的首地址
大小 正好是16个字节 目前还未初始化 所以使用CC填充
下面就是直接调用了Sub类的构造函数我们单步进去看看

我们跟到Sub的构造函数中可以很明显的看到 先调用了 基类Base 的构造函数 完成Base的成员初始化
然后再初始化Sub类中自身的成员变量
push ebp
004018B1 mov ebp,esp
004018B3 push 0FFh
004018B5 push offset __ehhandler$??0Sub@@QAE@XZ (00447599)
004018BA mov eax,fs:[00000000]
004018C0 push eax
004018C1 mov dword ptr fs:[0],esp
004018C8 sub esp,44h
004018CB push ebx
004018CC push esi
004018CD push edi
004018CE push ecx
004018CF lea edi,[ebp-50h]
004018D2 mov ecx,11h
004018D7 mov eax,0CCCCCCCCh
004018DC rep stos dword ptr [edi]
004018DE pop ecx
004018DF mov dword ptr [ebp-10h],ecx
004018E2 mov ecx,dword ptr [ebp-10h]
004018E5 call @ILT+395(Base::Base) (00401190)
004018EA mov dword ptr [ebp-4],0
004018F1 push offset @ILT+215(std::endl) (004010dc)
004018F6 push offset string "Sub \xb9\xb9\xd4\xec\xba\xaf\xca\xfd" (0046e01c)
004018FB push offset std::cout (00479a28)
00401900 call @ILT+665(std::operator<<) (0040129e)
00401905 add esp,8
00401908 mov ecx,eax
0040190A call @ILT+500(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011f9)
0040190F mov eax,dword ptr [ebp-10h]
00401912 mov dword ptr [eax+8],1Eh
00401919 mov ecx,dword ptr [ebp-10h]
0040191C mov dword ptr [ecx+0Ch],28h
00401923 mov dword ptr [ebp-4],0FFFFFFFFh
0040192A mov eax,dword ptr [ebp-10h]
0040192D mov ecx,dword ptr [ebp-0Ch]
00401930 mov dword ptr fs:[0],ecx
00401937 pop edi
00401938 pop esi
00401939 pop ebx
0040193A add esp,50h
0040193D cmp ebp,esp
0040193F call __chkesp (00406f70)
00401944 mov esp,ebp
00401946 pop ebp
00401947 ret
这里还可以很明显的看到 首先用 mov dword ptr [ebp-10h],ecx
把我们定义的Sub类的对象的首地址 存放到了 ebp-10h 的一个临时变量中
然后调用完基类Base的构造函数后
0040190F mov eax,dword ptr [ebp-10h]
00401912 mov dword ptr [eax+8],1Eh
00401919 mov ecx,dword ptr [ebp-10h]
0040191C mov dword ptr [ecx+0Ch],28h
对Sub类中的成员 a 、b分别赋值
mov dword ptr [eax+8],1Eh 这一段 可以 = [this+0x8] = 30
mov dword ptr [ecx+0Ch],28h 这一段 可以 = [this+0xc] = 40
有没有疑问说为什么 a的地址跑到了 this+8的位置了?
其实前8个字节已经被Base中的成员变量占用了
我们可以看看内存中的数据

可以看到 this+0 与 this+4 的位置分别存放了 十进制 的10、20的整数值
而this +8 与 this +0xc 的位置 分别存放了 十进制的 30 、40的整数值
到了这里 大家应该明白了 其实继承就是 数据的复制这个说法了吧 其实就是编译器帮我们自动生成了很多我们看不到的代码
现在看到这里 我提出一个小问题 怎么修改 Base中的x 和y的值呢?

相信聪明的你已经懂了

c++ 基础知识回顾 继承 继承的本质就是数据的copy的更多相关文章
- Java基础知识回顾(一):字符串小结
Java的基础知识回顾之字符串 一.引言 很多人喜欢在前面加入赘述,事实上去技术网站找相关的内容的一般都应当已经对相应知识有一定了解,因此我不再过多赘述字符串到底是什么东西,在官网中已经写得很明确了, ...
- C#基础知识回顾-- 反射(1)
C#基础知识回顾-- 反射(1) 反射(reflection)是一种允许用户获得类型信息的C#特性.术语“反射”源自于它的工作方式: Type对象映射它所代表的底层对象.对Type对象进行查询可以 ...
- Java基础知识回顾之七 ----- 总结篇
前言 在之前Java基础知识回顾中,我们回顾了基础数据类型.修饰符和String.三大特性.集合.多线程和IO.本篇文章则对之前学过的知识进行总结.除了简单的复习之外,还会增加一些相应的理解. 基础数 ...
- C#学习笔记(基础知识回顾)之值类型和引用类型
一:C#把数据类型分为值类型和引用类型 1.1:从概念上来看,其区别是值类型直接存储值,而引用类型存储对值的引用. 1.2:这两种类型在内存的不同地方,值类型存储在堆栈中,而引用类型存储在托管对上.存 ...
- C++ 基础知识回顾总结
一.前言 为啥要写这篇博客?答:之前学习的C和C++相关的知识,早就被自己忘到一边去了.但是,随着音视频的学习的不断深入,和C/C++打交道的次数越来越多,看代码是没问题的,但是真到自己操刀去写一些代 ...
- java基础知识回顾之---java String final类普通方法
辞职了,最近一段时间在找工作,把在大二的时候学习java基础知识回顾下,拿出来跟大家分享,如果有问题,欢迎大家的指正. /* * 按照面向对象的思想对字符串进行功能分类. * ...
- C#基础知识回顾-- 反射(3)
C#基础知识回顾-- 反射(3) 获取Type对象的构造函数: 前一篇因为篇幅问题因为篇幅太短被移除首页,反射这一块还有一篇“怎样在程序集中使用反射”, 其他没有什么可以写的了,前两篇主要是铺垫, ...
- C#基础知识回顾--线程传参
C#基础知识回顾--线程传参 在不传递参数情况下,一般大家都使用ThreadStart代理来连接执行函数,ThreadStart委托接收的函数不能有参数, 也不能有返回值.如果希望传递参数给执行函数, ...
- python爬虫主要就是五个模块:爬虫启动入口模块,URL管理器存放已经爬虫的URL和待爬虫URL列表,html下载器,html解析器,html输出器 同时可以掌握到urllib2的使用、bs4(BeautifulSoup)页面解析器、re正则表达式、urlparse、python基础知识回顾(set集合操作)等相关内容。
本次python爬虫百步百科,里面详细分析了爬虫的步骤,对每一步代码都有详细的注释说明,可通过本案例掌握python爬虫的特点: 1.爬虫调度入口(crawler_main.py) # coding: ...
- scrapy实战1,基础知识回顾和虚拟环境准备
视频地址 https://coding.imooc.com/learn/list/92.html 一. 基础知识回顾 1. 正则表达式 1)贪婪匹配,非贪婪匹配 .*? 非贪婪 . ...
随机推荐
- POLARDB 2.0 重磅升级,分别支持Oracle与PostgreSQL
点击订阅新品发布会! 新产品.新版本.新技术.新功能.价格调整,评论在下方,下期更新!关注更多内容,了解更多 最新发布 POLARDB 2.0 重磅升级 2019年6月19日15时,阿里云 POLAR ...
- HZOJ matrix
完全没有思路,状压到死没调出来……吐槽一下这题目描述的好不清楚啊好多人都理解错题了…… 题解: 真的挺神仙的,因为有每列最多放1个的限制,所以考虑按列dp,设f[i][j]表示考虑前i列在[1,i]中 ...
- Laravel如何引用第三方(自定义)库
想做一个网页抓取的功能,底层使用php的laravel框架. 这里使用phpQuery库来实现网页抓取,这里不做介绍. 需要了解的可以百度,或者等我填坑. 下载最新版本可以前往https://code ...
- @noi.ac - 508@ 01背包
目录 @description@ @solution@ @accepted code@ @details@ @description@ 有一天你学了一个能解决01背包问题的算法,你决定将这个算法应用到 ...
- C#面向对象--练习题
public class Program { //用户自定义:我们自己定义这种数据类型 public struct jiegouti// 结构体前面加上public, 可供外界访问 { public ...
- Python--day47--mysql索引种类
- Codeforces Round #189 (Div. 1 + Div. 2)
A. Magic Numbers 不能出现连续的3个4,以及1.4以外的数字. B. Ping-Pong (Easy Version) 暴力. C. Malek Dance Club 考虑\(x\)二 ...
- netstat 显示当前网络连接的统计信息
C:\Users\Administrator\Desktop\hsqldb-2.3.2\data>netstat -h Displays protocol statistics and curr ...
- 【t018】派对
Time Limit: 1 second Memory Limit: 256 MB [问题描述] N头牛要去参加一场在编号为X(1≤X≤n)的牛的农场举行的派对(1≤N≤1000),有M(1≤M≤10 ...
- 【codeforces 761C】Dasha and Password(动态规划做法)
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...