样板例子如下:using System;
public abstract class A  


        public A()  
       { 
            Console.WriteLine('A'); 
        } 

        public virtual void Fun()  
       { 
            Console.WriteLine("A.Fun()"); 
       } 
} public class B: A  

        public B() 
       { 
            Console.WriteLine('B'); 
        } 

        public new void Fun()
       { 
            Console.WriteLine("B.Fun()"); 
        } 

        public static void Main()  
       { 
                     A a = new B();
   a.Fun();
   Console.ReadLine();
        } 
}这段程序的输出是A
B
A.Fun()Q1:不理解为什么a.Fun()输出的居然是  “A.Fun()”我的理论:
由  A a=new B()   这一句编译以后,a应该算是B的对象,为什么 a.Fun()输出的不是“B.Fun()”Q2:如果将B类中的         public new void Fun()
      
改为public override void Fun()
那么 a.Fun()输出的就是 “B.Fun()”了。请解释一下。
在这里,我理解的new就是用来隐藏父类的方法的。
override是用来重载的先写这么多,还有的疑问陆续登场

解决方案 »

  1.   

    没测试你的代码。
    不过既然A为abstract class,那你至少应该把class A地Fun设成
    public abstract void Fun(); //不提供任何实现
    这样才显得abstract像个abstract
      

  2.   

    各位大师不要让我看书了,书上写例子A都不是抽象的,所以是不是因为它是抽象的就出现了疑问,如果把类A的abstract去掉,而且将A a=new B()改为  A a=new A(),这样的话  a.Fun()输出的当然是“A.Fun()”了。书(C#高级编程P163,当然,下面的话是我自己理解了书上的东西然后写的)上育这样的一段这样解释的:基于(A不是抽象类)1。如果A中的Fun()不是virtual方法,那么无论a引用的是什么(意思是:不管A a=new B()  或者A a=new A()  ),a.Fun()输出的都是  “A.Fun()”   2。如果A中的Fun()是virtual方法,那么在运行时,检查a引用的时哪个实例,然后确定属于哪个类,并调用相应的Fun(),那么就是说,如果A a=new B()这种情况下,a.Fun()输出的就应该是  “B.Fun()”
    (对于2这种情况, 如果将B类中的         public new void Fun()            改为public override void Fun()                  那么输出的的确是“B.Fun()”但是如果 B类中的Fun()方法  依然是    public new void Fun()  这样声明的话  输出的结果还是“A.Fun()”)
      

  3.   

    回复人: namhyuk(namhyuk) ( ) 信誉:100 
    这个不是说抽象类像不像抽象类的问题啊题目就是这样的了。。
      

  4.   

    不管A是否为抽象类。。A a=new B()  对a进行GetType()方法的调用。得到的都是 B,既然是B,那么是不是说,a就是B的引用实例呢?
    如果是的话,那么根据上面说的
    2。如果A中的Fun()是virtual方法,那么在运行时,检查a引用的时哪个实例,然后确定属于哪个类,并调用相应的Fun(),那么就是说,如果A a=new B()这种情况下,a.Fun()输出的就应该是  “B.Fun()”
    为什么输出的还是“A.Fun()”,而不是“B.Fun()”呢?
      

  5.   

    overrideusing System;
    public abstract class A  


            public A()  
           { 
                Console.WriteLine('A'); 
            } 

            public virtual void Fun()  
           { 
                Console.WriteLine("A.Fun()"); 
           } 
    } public class B: A  

            public B() 
           { 
                Console.WriteLine('B'); 
            } ///////////////////////////////////////////
    将new 改为override
            public override void Fun()
           { 
                Console.WriteLine("B.Fun()"); 
            } 

            public static void Main()  
           { 
                         A a = new B();
       a.Fun();
       Console.ReadLine();
            } 
    }
      

  6.   

    首先是你要达到什么效果。
    如果要动态绑定,那就virtual + override.如果想A a = new B();时管它B里有同名方法,但照样想执行A.Fun(),那就new.关键是明白为什么要用new.
      

  7.   

    abstract class A  是别人家开发的类库。
    我要用它,那么我继承它。
    public class B: A  继承后我不小心声明了一个和基类库中Fun()方法同名的一个Fun()方法。
    A a = new B();
    a.Fun();
    这时,不加new,编译器就提出警告。它不知道你要执行哪个,你想动态捆绑,执行继承类的Fun(),你就加个override,编译器会告诉你。要么,加个new,为什么加new,你既然不是前一种情况,那你就明确告诉我Fun在B里是一种新的实现方法,它跟A里的Fun没关系。
    也不知道我的理解对不对。
      

  8.   

    virtual关键字功能:不论对象是否被转为基类型,都只调用位于继承链最末端的实现方法。
    new关键字是覆盖基类型方法,并不属于“继承链”所以在lz程序中,继承链最末端就是基类的Fun(),
    而B类改为override以后,继承链最末端变为B.Fun(),因此执行B.Fun()
      

  9.   

    virtual关键字功能:不论对象是否被转为基类型,都只调用位于继承链最末端的实现方法。
    这个说法好像比较正确的唉。。不过还有一个不明白的。。
    A a=new B()  这样的话。。a应该算是B的对象的吧。B类本身也有Fun()函数,为什么不调用自己的呢?
      

  10.   

    反编译后 new 修饰符被隐去了,变成: public void Fun()

    Console.WriteLine("B.Fun()"); 
    }
      

  11.   

    不过还有一个不明白的。。
    A a=new B() 这样的话。。a应该算是B的对象的吧。B类本身也有Fun()函数,为什么不调用自己的呢?
    //===========================================================================类B有两个Fun函数,一个在VTable里,用于晚绑定,一个是普通的用于早绑定的函数
    new关键字的意思就是忽略原来继承的那个函数,使用新定义的函数。
    但是这里你是用a.Fun去调用,编译器认为是虚函数调用,所以调用的是B的VTable中的那个函数(就是从A继承来的),而在类型B上调用Fun,将不使用VTable,使用早绑定
    (类A的VTable:               Object::ToString()
                                Object::Equals()
                                Object::GetHashCode()
                                Object::GetType()
                                A::Fun()
    类B的VTable :               Object::ToString()
                                Object::Equals()
                                Object::GetHashCode()
                                Object::GetType()
                                A::Fun()    //从A继承来
    )
      

  12.   

    你的描述有问题,如下:
    “override是用来重载的”首先这句话就有问题,你还没有理解什么是重载,什么是重写.
    xs
      

  13.   

    new virtual override 等关键字的用途就知道怎么回事了。
      

  14.   

    但是这里你是用a.Fun去调用,编译器认为是虚函数调用,所以调用的是B的VTable中的那个函数(就是从A继承来的),而在类型B上调用Fun,将不使用VTable,使用早绑定为什么这里用a.Fun()调用就让编译器认为是虚函数调用呢???
    为什么不会认为它是类B上的Fun()呢?恳求  回复人: Jim3(Jim) ( ) 信誉:105   大人帮忙说清楚一点。谢谢了。
      

  15.   

    参看 
    MSDN 对virtual 和override的说明和示例
    http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/csref/html/vclrfVirtualPG.asp简单地说就是除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。 在静态属性上使用 virtual 修饰符是错误的。 
    通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性
      

  16.   

    Q1:不理解为什么a.Fun()输出的居然是  “A.Fun()”
    我的理论:
    由  A a=new B()   这一句编译以后,a应该算是B的对象,为什么 a.Fun()输出的不是“B.Fun()”
    /*********************************************************************
    你说a应该算是B的对象,这是不对的。a就是A类型的一个引用变量,a可以引用A类型的对象,也可以引用B类型的对象。在这里a.Fun()应该输出“A.Fun()”。为什么呢,因为B类里面的Fun()是用new修饰的,我想你的想法是:希望用父类的变量引用子类的对象,用以实现动态邦定。如果是这样,你用了new隐藏B的方法,a不会顺着下去找B的方法的。如果你用override修饰B的方法,a.Fun()就bind到B类的方法了。罗嗦说了这么多,不知道说清楚没有。
    总之,一句话,你错在“这一句编译以后,a应该算是B的对象”,a绝对不是B的对象。a只不过可以通过as方法,去调用B有而A没有的方法。记住:a只是A类型的变量!
      

  17.   

    Q2:如果将B类中的         public new void Fun()      
    改为
    public override void Fun()
    那么 a.Fun()输出的就是 “B.Fun()”了。
    请解释一下。
    在这里,我理解的new就是用来隐藏父类的方法的。
    override是用来重载的。
    /*****************************************************8
    你的理解是正确的!
    上面我已经解释了,希望能对你有一点帮助!
      

  18.   

    为什么这里用a.Fun()调用就让编译器认为是虚函数调用呢???
    为什么不会认为它是类B上的Fun()呢?
    //===========================================================================假如你是编译器,你能从a.Fun()分析出要调用的是类B的Fun()么?至少目前的编译器没有这么做编译器的规则是:首先看你在那个类型上调用函数其次看你调用的函数是否虚函数,是就启用晚绑定,否就早绑定