关于封装、继承、多态的学习笔记

CLR管理内存的区域有三块:
1、线程的堆栈:用于分配值类型示例。有操作系统管理,不受垃圾收集器的控制。生命周期结束后自动释放其存储单元。栈的执行效率高,容量有限
2、GC堆:用于分配小对象实例(<85000字节)。可能会被压缩。
3、LOH(Large Object Heap):用于分配大对象实例。不会被压缩,只在完全GC回收时被回收。

值类型被分配在托管堆上的时机:a、作为类的字段时;b、值类型发生装箱操作时;

托管堆分为多个区域,其中重要的是:垃圾回收堆(GC Heap)和加载堆(Loader Heap)

GC Heap用于存储对象实例,受GC管理;
Loader Heap中记录对象的元数据相关信息,其中有一个Method Table(方发表);
Method Table中记录了存储的元素据信息,包括基类型、静态字段、实现的接口、所有的方法等;Loader Heap不收GC控制,生命周期为从创建到AppDomain卸载;

TypeHandle(类型句柄):指向对应实例的方法表。每个对象被创建时都包含该附加成员,占用4个字节的内存空间。每个类型对应一个方法表,方法表是在编译的时候就创建了,其中主要包含了类型的特征信息、实现的接口数目、方法表的slot数目等。

SyncBlockIndex,用于线程同步,每个对象创建时也包含该附加成员,用于管理对象同步。

NextObjPtr,由托管堆维护的一个指针,用于标识下一个新建对象分配时在托管堆中所处的位置。

对象在使用new关键字为其分配内存空间和初始化时,将进行如下操作:
a、CLR将按照其继承层次进行搜索,递归计算其类型本身和其所有父类型的字段所占的内存空间,直到计算到System.Object类型,返回总字节数。接着加上对象附加的成员的字节总数(TypeHandel和SyncBlockIndex),然后在堆的内存块中分配一个4Byte的倍数的最小大于计算出来的字节总数的地址空间。
b、CLR在当前AppDomain对应的托管堆上搜索,找到相应大小的连续空间进行分配。这过程中,NextObjPtr指针向前推进相应大小的字节,并清零原NextObjPtr和当前NextObjPtr之间的内存,这部分内存就是用来存放刚被创建的对象。
c、在分配内存这个过程中,如果空间不足,GC将启动垃圾回收操作累回收垃圾对象所占的内存。
d、最后调用对象构造器为对象进行初始化操作,完成整个创建过程。


封装是什么:封装就是一个包装,将包装的内外分为两个空间,对内实现数据私有,对外实现方法调用,保证了数据的完整性和安全性。

 

继承:

  1、在继承中,如果子类对象的方法重写了父类的方法,在子类实例的Method Table中子类的重写方法覆盖父类的被重写方法。

  2、如果子类有和父类同名的字段,子类的同名字段不会覆盖父类的同名字段。父类字段在托管堆中存储的顺序排在子类字段的前面。当用父类类型的引用指向子类类型的实例时,父类类型引用调用的同名字段是属于父类的字段。这是因为调用时按照顺序来查找的。


多态:同一操作作用于不同的实例,产生不同运行结果的机制。

多态的分类:强制的、重载的、参数的和包含的;基类继承式多态和接口实现式多态。

动态绑定:又叫晚期绑定,是区别静态绑定而言的(静态绑定在编译期就可以确定关联,一般是以方法重载来实现的;实质不存在)。动态绑定则在运行期通过检查虚拟方法表来确定动态关联覆写的方法,一般以继承和虚方法来实现。

.net中实现虚方法的动态绑定:
父类 a=new 子类();
a.b();
1、编译器首先检查父类中b方法是否实现为虚方法,没有的话直接调用,否则检查子类中是否重写了b方法,没有的话继续递归检查子类的父类,直至找到第一个重写了的b方法或递归完之后也是没有,调用父类b方法。

posted on 2013-11-13 17:45  wuwenmao  阅读(191)  评论(0编辑  收藏  举报

导航