虚方法

using System;
 
class A {
    public void F() { Console.WriteLine("A.F"); }
    public virtual void G() { Console.WriteLine("A.G"); }
}
class B : A {
    new public void F() { Console.WriteLine("B.F"); }
    public override void G() { Console.WriteLine("B.G"); }
}
class Test {
    static void Main() {
        B b = new B();
        A a = b;
        a.F();
        b.F();
        a.G();
        b.G();
    }
}

  这是今天看书的一段代码,mark!

  在该示例中,A 引入一个非虚方法 F 和一个虚方法 G。类 B 引入一个新的非虚方法 F,从而隐藏了继承的 F,并且还重写了继承的方法 G。根据对象初始化的过程,着眼于方法表的顺序:关注对象,从自身类向派生类搜索到第一个可以访问的同名方法。“在虚方法调用中,该调用所涉及的那个实例的运行时类型 (run-time type) 确定了要被调用的究竟是该方法的哪一个实现。在非虚方法调用中,相关的实例的编译时类型 (compile-time type) 是决定性因素。”(——《C#规范4.0》)由此可知,实例a b内存的布局前半部分是一致的,运行时类型b:B.F B.G 。编译类型a:A.F A.G B.G B.F  ,然后根据名称找方法,分别是 A.F B.F B.G B.G。

  对调用哪个实际方法实现起决定作用的是该实例的运行时类型(即引用类型 A),而不是该实例的编译时类型(即实际内存分配对象B)。

class A {
    public virtual void F() { Console.WriteLine("A.F"); }
}
class B : A {
    public override void F() { Console.WriteLine("B.F"); }
}
class C : B {
    new public virtual void F() { Console.WriteLine("C.F"); }
}
class D : C {
    public override void F() { Console.WriteLine("D.F"); }
}
class Test {
    static void Main() {
        D d = new D();
        A a = d;
        B b = d;
        C c = d;
        a.F();
        b.F();
        c.F();
        d.F();
    }
}

  C 类和 D 类包含两个具有相同签名的虚方法:一个是 A 引入的,另一个是 C 引入的。但是,由 C 引入的方法隐藏了从 A 继承的方法。因此,D 中的重写声明所重写的是由 C 引入的方法,D 不可能重写由 A 引入的方法。内存都D的布局,a.F搜索到B类有满足方法,b.F也是直接该类满足,c和d同理。此例产生输出:B.F B.F D.F D.F。

posted @ 2011-10-28 14:49  云是风的梦  阅读(201)  评论(0编辑  收藏  举报