[求解]基类引用不能访问子类public实例字段

 

最近一直比较纠结CLR在类型转换时到底做了些什么事情,在这里我撇开基本类型不谈,因为那些类型在转换过程中就是数据的扩充和裁切,这里主要讨论继承机制中的类型转换问题。

先看段简单代码

 1 class Father
2 {
3 public int i=10;// 声明为public类型是为了后面的验证
4 /// <summary>
5 /// 非虚实例方法
6 /// </summary>
7 public void IsFather()
8 {
9 Console.WriteLine("I'm father");
10 }
11 /// <summary>
12 /// 虚方法
13 /// </summary>
14 public virtual void MyName()
15 {
16 Console.WriteLine("I'm father");
17 }
18 }
19
20 class Child : Father
21 {
22 public strings="Test

";// 声明为public类型是为了后面的验证
23
24 /// <summary>
25 /// 非虚实例方法
26 /// </summary>
27 public void IsChild()
28 {
29 Console.WriteLine("I'm child");
30 }
31 /// <summary>
32 /// 重写实例方法
33 /// </summary>
34 public override void MyName()
35 {
36 Console.WriteLine("I'm child");
37 }
38 }

根据CLR Via C#中的介绍,我可以理解在继承机制中方法的调用原理,但是对实例字段的调用就不是很明确了,书中说到(下面一段内容摘自() Jeffrey Richter著 ,周靖译的《CLR Via C#》第三版,版权归著作权所有者,这里仅引用一下):

4-8  在线程栈上分配M3的局部变量

 然后,M3执行它的代码来构造一个Manager对象。这造成在托管堆中创建Manager类型的一个实例(也就是一个Manager对象),如图4-9所示37。可以看出,和所有对象一样,Manager对象也有一个类型对象指针和同步块索引。该对象还包含必要的字节来容纳Manager类型定义的所有实例数据字段,以及容纳由Manager的任何基类(本例就是EmployeeObject)定义的所有实例字段。任何时候在堆上新建一个对象,CLR都会自动初始化内部类型对象指针成员,让它引用与对象对应的类型对象(本例就是Manager类型对象)。此外,CLR会先初始化同步块索引,并将对象的所有实例字段设为null0(零),再调用类型的构造器(它本质上是可能修改某些实例数据字段的一个方法)。new操作符会返回Manager对象的内存地址,该地址保存在变量e中(e在线程栈上)。

 

以上内容说明了Employ 类型的应用e指向了一个Manager类型的实例,而在这个实例对象中包含了所有Manager类型以及其基类中定义的所有实例字段,如下图所示:

 

按理说既然e的引用指向了Manager对象的实例,就可以访问其实例中的任何可访问的资源,包括实例字段,

那么:

   class Program
{
static void Main(string[] args)
{
Father father = new Child();
Child child = new Child();
Console.WriteLine(father.s);
}
}

这里father.s应该是可以访问的,但是事实上是不能访问的。这里正是我疑惑的地方。

想了很久,我觉得应该是在Father father = new Child();进行隐式的类型转换时CLR做了一些事情,所以我想搞明白在这种情况下CLR会做些什么操作?

刚开始我觉得是改变了实例对象的类型对象指针,使得对象的类型发生了变化,但是后来觉得这样也不对,因为类型对象中并不存储实例字段,即便改变了类型对象的指针,也不可能知道是否存在这样的实例这段啊,而且根据实验的结果,无论怎样转换类型,对象实例的类型永远都是创建类型时类型对象指针指向的那个类型,即原本类型,事实上是不会被改变的。

 

百思不得其解,在这里求助高人,望大家不吝赐教!还请各位积极发表看法,讨论一下在类型转换时CLR会执行那些具体的操作。

 

转载于:https://www.cnblogs.com/ElvisWang/archive/2012/02/17/2355654.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值