其实 yarshray(saga jion) 讲的还是比较正确的。不愧是二星级的。 我只是补充点罢了。这里所牵涉到是类继承中的隐藏和重写两个概念。 源码中的语法很正确,无可挑剔。 A.F()没有声明为虚方法,只能被子类隐藏,而不能被重写。 而A.G()声明为虚方法,可以被重写。B.F()由于声明了 new ,所以 B.F() 将隐藏虚方法 A.F()。隐藏意味着 B 的实例调用 F() 时,将使用 B 中声明的 F() ,而不会与 A.F() 产生岐义。但隐藏并不表明 A.F()被重写,此时即使在同一个 B 类型的实例中 A.F() 与 B.F()是两个不同的方法。所以类型为 A 的实例在调用 F() 时仍然是 A 中原来定义的 F(),尽管所引用的对象是 B 类型。B.G()由于声明了 override ,所以 B.G() 将重写虚方法 A.G()。重写意味着 A.G() 将在创建子类 B 的实例时被 B.G() 覆盖,此时在一个 B 类型的实例中, A.G() 与 B.G()是指同一个方法,即 B.G()。当类型 A 的实例引用的对象是 B 类型的实例时,其实调用的仍旧是 A.G(),但由于 A.G() 被 B.G() 重写(覆盖),所以在实际运行时将使用子类 B 中定义的 G()。然而,在以下代码中: A a = new A(); a.G(); a.G()调用的是仍旧是 A 中定义的 G()。因为此时实例 a 引用的对象是 A 类型,无法获取重写版本的 G()。也就是说,此时 A.G() 并没有被重写(覆盖)。你也可以试一下这样的代码: class B:A { new public void F(){ Console.WriteLine("B.F") }; new public void G(){ Console.WriteLine("B.G");} } 使用同样的例程调试一下,对比一下结果,你会有所感悟的。OO 的多态性是很复杂的问题,C# 已经作了许多优化(相对于 C++),还是比较好掌握的。
更正: B.F()由于声明了 new ,所以 B.F() 将隐藏虚方法 A.F()。应改为: B.F()由于声明了 new ,所以 B.F() 将隐藏基类中的非虚方法 A.F()。当然方法的签名必须相同。否则是重载,而不是隐藏重写。重载是语法关键词 override 。隐藏是 hide ,用于解释 override 的行为。
虚方法我知道,关键是不知道编译时附值与运行是附值具体的内部操作差别再哪?那个不叫附值,叫引用,而且你必须要理解虚表这个概念
建议你看看C++对虚函数的解释那样会好些,这一点C#和C++是一致的!
因为G被改写了,而F不是虚函数,虚表里也没有
所以找不到!就还是a.F()
是因为:
派生类B的f()方法并没有覆盖A中的f()方法,而是导致它隐藏了
我只是补充点罢了。这里所牵涉到是类继承中的隐藏和重写两个概念。
源码中的语法很正确,无可挑剔。
A.F()没有声明为虚方法,只能被子类隐藏,而不能被重写。
而A.G()声明为虚方法,可以被重写。B.F()由于声明了 new ,所以 B.F() 将隐藏虚方法 A.F()。隐藏意味着 B 的实例调用 F() 时,将使用 B 中声明的 F() ,而不会与 A.F() 产生岐义。但隐藏并不表明 A.F()被重写,此时即使在同一个 B 类型的实例中 A.F() 与 B.F()是两个不同的方法。所以类型为 A 的实例在调用 F() 时仍然是 A 中原来定义的 F(),尽管所引用的对象是 B 类型。B.G()由于声明了 override ,所以 B.G() 将重写虚方法 A.G()。重写意味着 A.G() 将在创建子类 B 的实例时被 B.G() 覆盖,此时在一个 B 类型的实例中, A.G() 与 B.G()是指同一个方法,即 B.G()。当类型 A 的实例引用的对象是 B 类型的实例时,其实调用的仍旧是 A.G(),但由于 A.G() 被 B.G() 重写(覆盖),所以在实际运行时将使用子类 B 中定义的 G()。然而,在以下代码中:
A a = new A();
a.G();
a.G()调用的是仍旧是 A 中定义的 G()。因为此时实例 a 引用的对象是 A 类型,无法获取重写版本的 G()。也就是说,此时 A.G() 并没有被重写(覆盖)。你也可以试一下这样的代码:
class B:A
{
new public void F(){ Console.WriteLine("B.F") };
new public void G(){ Console.WriteLine("B.G");}
}
使用同样的例程调试一下,对比一下结果,你会有所感悟的。OO 的多态性是很复杂的问题,C# 已经作了许多优化(相对于 C++),还是比较好掌握的。
B.F()由于声明了 new ,所以 B.F() 将隐藏基类中的非虚方法 A.F()。当然方法的签名必须相同。否则是重载,而不是隐藏重写。重载是语法关键词 override 。隐藏是 hide ,用于解释 override 的行为。
我自己都越解释越糊涂了。Change :
重载是语法关键词 override 。隐藏是 hide ,用于解释 override 的行为。TO :
重写是语法关键词 override,有时也称为覆盖。隐藏是 hide ,用于解释 new 的行为。