前言

按照常规,类之间转换是通过副本构造函数,也可以叫拷贝函数实现。


正文

1
2
3
4
5
6
7
class Object{
public:
int data_0 = 1;
int data_1 = 2;
int data_2 = 3;
int data_3 = 4;
};

连续的内存,只要能知道data_0的内存地址,后面三个偏移一下也就得到了。

1
2
3
4
5
6
7
8
9
10
11
int main(){

Object obj;
int *readO = (int *)&obj;
std::cout << "obj地址:" << &obj << std::endl;
for (int i = 0; i < sizeof(obj); i++){
std::cout << "内存地址: " << &readO[i] << "值:" << readO[i] << std::endl;
}

return 0;
}

通过直接打印查看

可以看到int类型的内存占用之间相差四字节。

并且类的内存分配跟private和public那些没啥关系,当然前提是正常的类。


进行第一次派生

1
2
3
4
5
6
7
class son :public Object{
public:
int sdata_0 = 11;
int sdata_1 = 12;
int sdata_2 = 13;
int sdata_3 = 14;
};

看到son类继承了Object的属性
可以说是把Object的成员照搬了过来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class son :public Object{
/*
public:
int data_0 = 1;
int data_1 = 2;
int data_2 = 3;
int data_3 = 4;
*/
public:
int sdata_0 = 11;
int sdata_1 = 12;
int sdata_2 = 13;
int sdata_3 = 14;
};

第二次派生

1
2
3
4
5
6
7
class grandson :public son{
public:
int gsdata_0 = 21;
int gsdata_1 = 22;
int gsdata_2 = 23;
int gsdata_3 = 24;
};

按照顺序继承,成员变量的地址自然也就按照从父类继承的开始顺序开辟。


  1. 不同编译可能存在优化,地址不一定顺序
  2. 但是派生类的大小,肯定是包含父类的
  3. 构造函数按照基类派生类的顺序依次构造,析构函数则相反,先从派生类开始

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Object{
public:
int data_0 = 1;
int data_1 = 2;
int data_2 = 3;
int data_3 = 4;
};

class father{
public:
int data_0 = 1;
int data_1 = 2;
int data_2 = 3;
int data_3 = 4;
};

class son :public Object,public father{
public:
int sdata_0 = 11;
int sdata_1 = 12;
int sdata_2 = 13;
int sdata_3 = 14;
};

class grandson :public son{
public:
int gsdata_0 = 21;
int gsdata_1 = 22;
int gsdata_2 = 23;
int gsdata_3 = 24;
};

当重复继承的时候

能看到出现了两次1234
这是因为初始化在类中就完成了,你实际上直接访问是访问不到的,因为没有给编译器指定道路。
想要指定的话解决办法也就是作用域。

当然还有虚基类的方法。但是这个目前好像讲不明白,要有反汇编的能力,所以此处就简易过一下了。

1
2
3
4
5
6
7
class son :public virtual Object,public virtual  father{
public:
int sdata_0 = 11;
int sdata_1 = 12;
int sdata_2 = 13;
int sdata_3 = 14;
};

你会发现构造顺序变了,还多了一个值,这个值会代表什么。

而且我们知道,构造顺序肯定是先从基类开始的,只不过这里的内存布局好像被打乱了的样子。


结语

这个有点草率,前面都是正常的看看内存分析,后面改变虚基类的时候,打印出来的结果顺序比较奇怪,但是要从反汇编的角度才能看明白,可能就是对逆向的人会关注点,先搞正向就先留个印象得了。