中易网

C# 继承问题(父类,子类方法,字段之前的关系问题)

答案:4  悬赏:70  
解决时间 2021-01-15 07:43
  • 提问者网友:末路
  • 2021-01-15 04:12
C# 继承问题(父类,子类方法,字段之前的关系问题)
最佳答案
  • 二级知识专家网友:不如潦草
  • 2021-01-15 05:22
我给你说下C#继承发生的一些事情吧,或许你自己就能理解为什么会这样了。
ClassB b = new ClassB();这句话会发生如下操作:

(1)计算 b所需要的内存空间,并分配这些空间。很明显,这个内存空间除了要保存c#本身的一些东西外,重点来分析对于继承的类ClassB而言,它需要分配哪些空间。最重要的,你需要明白分配的内存空间只包含实例字段。(方法等其他东西是和具体的对象实例无关的,方法只是一段代码调用而已,这个你明白c++的话,应该很好理解数据合方法的区别吧。)
对于ClassB而言,它首先要分配的就是是继承了ClassA的实例字段s,然后分分配ClassB本身的字段,s,但是注意,两个同名s的字段会导致覆盖,也就是ClassB的字段会覆盖本来已经从A继承的s,所以此时,b对象的内存里只有一个s。当然,目前这个s为空。但必须明白它只有一个s。
(2)初始化这段内存空间,也就是创建对象b。你这里没有调用自定义的构造函数(你也没有定义),所以c#会调用默认的,默认的会干嘛呢?
①,先初始化父类,也就是先会调用ClassA的默认构造函数,但务必注意,这里并没有出现一个新的ClassA对象(具体细节需要的话,你追问我。)。这里他会把"ClassA"赋值给s。到这里就完成了父类即ClassA的默认构造函数的调用(我说的是调用ClassA构造函数,但我没说是实例化ClassA。主要这两者的区别)。
②调用本身的构造函数,同样是默认的,它会把"ClassB"赋值给s字段,到这里,s已经变成"ClassB"了。
(3)把这段内存空间指向变量b,ClassB b = new ClassB();执行完毕。
对应方法:
public override void Show()
{
base.Show();
Console.WriteLine(this.s);
}

到b.Show();这里就很好理解了。

首先调用base.Show()。注意,你需要理解这个base表示的是调用父类的方法而已,但是并没有父类的实例也就是没有新的ClassA对象产生。实际上,因为B是继承自A的,所以C#是完全认可b对象就是ClassA的一个实例化对象(但你需要明白,在这种意义上,它自包含ClassA本身所定义的东西)。所以
public virtual void Show()
{
Console.WriteLine(this.s);//为什么在这this 是Test.ClassB 但this.s确是"ClassA"
Console.WriteLine(this.GetType());
}
这段代码里,this其实就是实例化的对象b而已,只是此时它只能访问ClassA定义的东西而已。所以this.s会是“ClassB”。而且我没猜错的话,此时的this.GetType同样显示的是ClassB,而不是ClassA。因为很好理解,b真正的类型是ClassB。

然后就是执行ClassB里的方法Console.WriteLine(this.s),这里的this同样是指向b对象的,但此时已经是彻底的b对象了,可以访问b对象里的所有东西了。

说了这么多,这段过程是重点你要能理解this,并不是指向this所在的类的,因为this是和实例即对象相关,this指向的是对象。但是C#的多态允许子类的实例作为父类的引用,
比如:
Class b=new ClassB();ClassA a=b;
我相信这段代码你比较容易理解,同样,在你的方法调用里 ,ClassA里的this指向的是b这个对象,和ClassA a=new ClassB()的道理是一样的。
呵呵,说了这么多,不知道我说明白了多少,也不知道你理解了多少。因为对于C#的多态,clr内部实现是有很多过程来完成的。而这些不是这几百字能搞定的。
有啥疑问就追问吧。不过我过年不会上网的。
如果你对c#的底层感兴趣的,我推荐你读读clr via c#,然后读读《你必须知道的.net》好像是叫着名字,对理解clr很有帮助。
全部回答
  • 1楼网友:几近狂妄
  • 2021-01-15 07:44
面试的题目吧
追问:非面试题,哥们,你想多了,我想理解的是this这个,它引用的地址究竟有何变化,而C#一般不讲内存或地址,不像C++,基本上原理都讲到
  • 2楼网友:动情书生
  • 2021-01-15 07:33
ClassB中的Show()方法不应该重写基类的Show()方法。应该将ClassB中的Show()方法的定义这样改:
public new void Show()//不重写,而是覆盖基类的Show()方法。
{
base.Show();//调用基类的Show()方法。
Console.WriteLine(this.s);
}

希望对你有帮助!
追问:这样就不存在我想要问的东西了,那么我想问下:
如何实现像Object类一样,让所有自定义的类都默认继承它(即class ClassA:Object(不用这样写))
  • 3楼网友:夜余生
  • 2021-01-15 06:14

虚方法中 系统会默认个 隐试构造函数  public  ClassA(){}    父类的方法可以被子类重写,也可以不重写。你在子类show方法中调用父类show方法没必要  直接由构造函数传参就可以 不必要再 子类和父类中单独定义字段 构造函数可以使有参数的 也可以是无参构造函数 string s=“classA”;可以通过有参构造函数传递


我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息!
大家都在看
推荐信息