C++逆向分析——继承
继承
struct Person {
int
age;
int
sex;
};
struct Teacher {
int
age;
int
sex;
int
level;
int
classId;
};
如上代码中可以看见,Teacher类与Person类都存在着相同的2个成员age和sex,那么这就相当于重复编写了,我们可以通过继承的方式避免这样重复的编写(当前类名称:要继承的类名称):
struct Teacher:Person {
int
level;
int
classId;
};
创建对象的对应反汇编代码如下,可以清晰的看见与我们正常的内存布局是一样的:
那么继承是什么?这就很好理解了,继承的本质就是数据复制,子类(派生类)继承(复制)父类(基类)的数据,在这里Person父类(基类),Teacher为子类(派生类);继承可以减少重复代码的编写。
假设,子类中存在一个与父类中相同的成员会如何?
struct Person {
int
age;
int
sex;
};
struct Teacher:Person {
// Inherit
int
age;
int
classId;
};
我们可以创建一个对象来看一下对应的宽度和反汇编代码:
void
main() {
Teacher t;
t.age =
30
;
t.sex =
1
;
t.classId =
20
;
printf(
"%d"
, sizeof(t));
printf(
"%d"
, sizeof(t));
return
;
}
首先看下数据宽度,我们会发现是16,那也就是说这里不管如何你只要继承了,在编译器中两个成员还是会直接添加过来,Teacher的成员依然是4个「4成员*4数据宽度(int类型) = 16」
再来看下反汇编代码:
之前我们已经看过了正常的内存布局了,在这里,很明显,少了一个0x10位置的成员,那么按照内存布局应该是这样的:
0x10 → Person.age
0x0C → Person.sex
0x08 → Teacher.age
0x04 → Teacher.classId
而在这里创建对象编译器使用的age成员默认就是当前类Teacher的成员;想要使用父类中的成员可以使用这种方式(对象名.父类名称::成员名称):
void
main() {
Teacher t;
t.Person::age =
30
;
// Father
t.age =
30
;
t.sex =
1
;
t.classId =
20
;
return
;
}
子类与父类成员重名的问题我们可以通过这种方式解决,但是在实际应用中还是尽量避免这种问题比较好。
我自己实践下内存布局:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <stdio.h> struct Person { int age; int sex; }; struct Teacher :Person { // Inherit int age2; int classId; }; void main() { Teacher t; t.age = 30; //ebp-24 t.age2 = 99; //ebp-16 t.sex = 1; //ebp-20 t.classId = 20; //ebp-12 printf ( "%d" , sizeof (t)); printf ( "%d" , sizeof (t)); return ; } |
ODB里看到的:
vs 2022里反汇编,可以看到父类age的变量地址对应的是[t]这个基址。==》看后面那个图!
我们可以多次继承么,或者说继承仅仅局限于子、父关系么?如下代码,B继承了A,C继承了B,C是否只继承了B的v和n?
struct A {
int
x;
int
y;
};
struct B:A {
int
v;
int
n;
};
struct C:B {
int
p;
int
o;
};
我们可以来打印一下C的数据宽度:
结果是24,那么就说明C不仅仅继承了B,还继承了A;再换个说法就是,继承的本质是数据的复制,那也就是说当复制完(继承)后才是其本身,B的本身就是4个成员x、y、v、n。==》看这个图就完全明白了!!!
除了这种方式以外,我们想实现同样的效果可以使用多重继承(当前类:继承的类A, 继承的类B):
struct A {
int
x;
int
y;
};
struct B {
int
v;
int
n;
};
struct C:A,B {
// Multiple
int
p;
int
o;
};
但这种方式在很多面向对象语言中是不允许时间的,在C++中是可以使用的,其内存分布也与第一种方式不一样:
最后:继承的类A和继承的类B的顺序,谁在前,谁就在内存分布中的前面;不推荐使用多重继承,这会增加程序的复杂度。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2020-04-09 OWASP TOP10 Web应用十大安全风险_2017
2020-04-09 移动互联网恶意程序描述格式 ——移动端恶意软件分类再合适不过了
2020-04-09 用短信传播病毒:最新Android手机勒索软件Koler
2020-04-09 2019年Android恶意软件专题报告:未来移动安全呈现四大趋势——资费消耗与隐私窃取分别以高达46.8%和41.9%的占比,成为横行无忌的主要恶意软件类型,其次分别为远程控制、流氓行为、恶意扣费和欺诈软件。
2020-04-09 2018年Android恶意软件专题报告
2020-04-09 浅析Android恶意应用及其检测技术
2020-04-09 Android恶意软件特征及分类