class Father
{
     public virtual void Fun(){}     public void Method(){}
}class Sun
{
     public override void Fun(){}     // 重写父类的 Fun 方法     pbblic new void Method(){}       // 隐藏父类的 Method 方法
}
比如上面这个例子
1. 关于 Fun 方法其实是子类在虚方法表中用新的 Fun 入口地址替换了继承的父类的 Fun 的地址;
2. 关于 Method ,烦请解释下在虚方法表中的是怎么操作的?能有什么权威的资料可以查查,谢谢!

解决方案 »

  1.   

    Don Box 的 .net 本质论, 第六章 - Methods
      

  2.   

    C#重载:同一个作用域内发生(比如一个类里面),定义一系列同名方法,但是方法的参数列表不同。这样才能通过传递不同的参数来决定到底调用哪一个。而返回值类型不同是不能构成重载的。C#重写:继承时发生,在子类中重新定义父类中的方法,子类中的方法和父类的方法是一样的 例如:基类方法声明为virtual(虚方法),派生类中使用override申明此方法的重写.C#隐藏:基类方法不做申明(默认为非虚方法),在派生类中使用new声明此方法的隐藏。C#重载时,根据参数选择调用的方法;C#重写时,访问父类子类皆调用子类的重写方法;C#隐藏时,访问父类则调用父类的方法,子类子类的方法。C#隐藏(new)示例:using    System;    
    class    A    

    public    void    F() 
     {  
     Console.WriteLine("A.F"); 
    }   
     } 
     class    B:    A 
      { 
      new    public    void    F() 
    {          
      Console.WriteLine("B.F"); 
     }  
    }  
     class    Test  
     {   
    static void Main(string[] args) 
      {  
    B    b    =    new    B(); 
                b.F(); 
              A    a    =    b;   
             a.F();   
         } 
      }   输出为  B.F  A.F  C#重写virtual(虚方法)示例  01.using    System; 
    class    A   

     public    virtual    void    F()  
        {   
         Console.WriteLine("A.F");   
         }    
     }    
    class    B:    A   
    {    
     public    override    void    F()  
         {   
            Console.WriteLine("B.F");    
      }    
    }    
    class    Test   
    {    
     static    void    Main()    
         {    
            B    b    =    new    B(); 
                b.F();  
             A    a    =    b;   
               a.F();    
         }    
     }  输出为  B.F  B.F补充:重写override一般用于接口实现和继承类的方法改写,要注意1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;4、被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。
      

  3.   

    我的理解:
    pbblic new void Method(){}       // 隐藏父类的 Method 方法
    因为不是虚方法,所以此函数不会出现在虚方法表中。
    如果一个类或其基类没有虚函数,那么这个类也不存在虚方法表。
      

  4.   

    学习,估计LZ是说C和C井交互那部分的吧
      

  5.   


    同意你对public new void Method(){}的解释
    但我认为一个类或者基类不管有没有虚函数,都存在虚方法表!补充:
    如果子类不写这个函数,那么调用子类的Method,实际上是调用父类的Method的地址
    子类写new void Method(){},实际上是告诉编译器这个时候要调用子类自己的Method的地址
    这样就实现了隐藏父类的Method方法的目的
      

  6.   

    C#的这部分我没有深入理解过我是按C++的类来理解的,或许有出处,你有相关的资料吗?可以共享一下吗?有的时候事实和认为是两码事儿
    虚方法表(virtual method table):当生成一个对象时,编译器将类对象的前四个字节设置为虚方法表的地址,构造过程中先构造基类,为基类对象填表,再构造子类,为子类(本层次)的虚表填表,这样,在构造函数中调用虚方法是不是发生多态(本层次的多态)的;当然,在C#中,我试过,和C++完全不一样,可以产生多态
    如果你有资料,可否共享一下?谢谢!
      

  7.   


    调用父类的Method地址并不等于调用虚方法表,这点我同意6楼的说法,有虚方法时才需要维护虚方法表的,这点和C++一样的概念,Thinking of C++中就有提到,由于这点的存在,使用虚方法带来的是效率的下降。但是换来了一个多态,还是划算的。
      

  8.   

    这个不太了解,C#在构造函数调用的时候,是有多态存在的,C++不知道,依稀记得好像和
    普通继承或是虚继承还是有关的,两者的顺序不同,至于C#的构造分析,可以看
    《.Net2.0面向对象编程解密》记得有对CLR的构造顺序和方法表作过具体的分析,我手头没书,不记得具体的说法了
      

  9.   

    我摘抄了一段,不过此处 Method Slot Table 怎么解释?方法槽表(Method Slot Table)
    在方法表中包含了一个槽表,指向各个方法的描述(MethodDesc),提供了类型的行为能力。方法槽表是基于方法实现的线性链表,按照如下顺序排列:继承的虚方法,引入的虚方法,实例方法,静态方法。类加载器在当前类,父类和接口的元数据中遍历,然后创建方法表。在排列过程中,它替换所有的被覆盖的虚方法和被隐藏的父类方法,创建新的槽,在需要时复制槽。槽复制是必需的,它可以让每个接口有自己的最小的vtable。但是被复制的槽指向相同的物理实现。
      

  10.   

    因为所有的C#类都是直接或间接从Object继承而来的,而Object自身拥有几个虚方法所以也就不足为怪了,
    谢谢分享。