Skip to content

Commit

Permalink
Improve c++_object_model
Browse files Browse the repository at this point in the history
  • Loading branch information
selfboot committed Apr 11, 2024
1 parent 588fd0b commit 20fd2e8
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 2 deletions.
Binary file added images/20240409_c++_object_model_inherit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 9 additions & 2 deletions source/_drafts/c-object-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ int main() {
## 类继承的内存布局

当然,既然是在聊面向对象的类,那就少不了继承了。我们还是从具体例子来看看,在继承情况下,类的内存布局情况。

### 不带虚函数的继承

先来看看不带虚函数的继承,示例代码如下:
Expand Down Expand Up @@ -286,14 +287,17 @@ int main() {
}
```
编译运行后,用 GDB 打印成员变量的内存分布,发现 `Derived` 类的对象在内存中的布局首先包含其基类`Basic`的所有成员变量,紧接着是 Derived 类自己的成员变量。
编译运行后,用 GDB 打印成员变量的内存分布,发现 `Derived` 类的对象在内存中的布局首先包含其基类`Basic`的所有成员变量,紧接着是 Derived 类自己的成员变量。整体布局如下图:
![继承类的内存布局](https://slefboot-1251736664.file.myqcloud.com/20240409_c++_object_model_inherit.png)
其实 C++ 标准并没有规定在继承中,基类和派生类的成员变量之间的排列顺序,编译器可以自由发挥的。但是大部分编译器在实现中,都是基类的成员变量在派生类的成员变量之前,为什么这么做呢?因为这样实现,**使对象模型变得更简单和直观。不论是基类还是派生类,对象的内存布局都是连续的,简化了对象创建、复制和销毁等操作的实现。**我们通过派生类对象访问基类成员与直接使用基类对象访问时完全一致,一个派生类对象的前半部分就是一个完整的基类对象。
对于成员函数(包括普通函数和静态函数),它们不占用对象实例的内存空间。不论是基类的成员函数还是派生类的成员函数,它们都存储在程序的代码段中(.text段)。
### 带有虚函数的继承
带有虚函数的继承,稍微有点复杂了。
带有虚函数的继承,稍微有点复杂了。在前面继承例子基础上,增加一个虚函数,然后在 main 中用多态的方式调用。
```c++
#include <iostream>
Expand Down Expand Up @@ -339,6 +343,8 @@ int main() {
}
```

这种情况下,对象的内存布局是什么样?虚函数的多态调用又是怎么实现的呢?


## 地址空间布局随机化

Expand All @@ -360,3 +366,4 @@ int main() {

## 总结


0 comments on commit 20fd2e8

Please sign in to comment.