随笔 - 576  文章 - 0  评论 - 62  阅读 - 219万

不同类型的指针

1、思考,不同类型的指针,到底有什么区别?

  指向Animal的指针和指向Dog的指针,到底有什么区别?首先,指针的表示方法相同,指针的内容相同,都是一个int,表示地址。区别只是指向对象的类型不同(好像是废话)。这有什么意义呢? 这其实是告诉了编译器如何解释这个地址中的内存内容以及大小。也就是说,对于指向Animal 的指针,编译器把指向内容当作一个Animal,对于指向Dog 指针,编译器把指向的内容当作Dog。

2、那么,问题来了,Animal* pa = new Dog(),是怎么做到运行期多态的呢?

  pa的表面类型是Animal,真实类型是Dog,编译器在编译时只知道pa的表面类型,那么把pa当作Animal来解释,能不能做到运行时多态呢?简单回忆一下,Animal对应一个虚方法表(虚方法表可认为一个数组,元素是方法指针),Dog对应一个虚方法表,可以认为Dog中的虚方法表是整体拷贝了Animal 的虚方法表,对于重写的方法在对应的位置换上重写后的方法,对于新增的虚方法,加在虚方法表的最后。对象的内存中只有实例字段和vptr,vptr指向vtbl(虚方法表),根据对应的方法,在vtbl对应的位置上,找到方法指针,进而找到方法。

  对于Animal对象和Dog对象,可认为在相同位置都放着vptr。这样的话,pa指向内存中的一个Dog对象,我把指向的内容当作Animal来解释,也能找到vptr,但是这个vptr指向Dog类的虚方法表。由于Dog类中虚方法表,是在Animal虚方法表的基础上,进行了替换,这就构成了运行时多态。

3、现在考虑,Animal和Dog都有一个Name字段,pa->Name 访问是Animal的字段,还是Dog 的字段呢?  

  Animal对象和Dog对象的内存分布,举例来说,Animal对象为:age,Name,vptr,那么Dog对象的内存分布就是age,Name,vptr,Name。前面Name的作用域是父类,后面Name的作用域是子类,子类作用域小于父类作用域。

  编译器把pa指向的内容,当作Animal来解释,取的是Animal的字段。如果想要取出Dog 的Name字段怎么办呢?当然是,告诉编译器,把pa指向的内容当作Dog来解释,强制类型转化为Dog指针。

posted on   Andy Niu  阅读(1628)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

点击右上角即可分享
微信分享提示