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();
    }
} A a = b; 这个a到底是A类的还是B类的啊,为什么 a.F();a.G(); 显示的是B.F B.G呢 谢谢

解决方案 »

  1.   

     A a = b; 这个a到底是A类的还是B类的啊
    前面不是用A定义的吗?你觉得呢?他只是用A的子类B来实例化
    第二个问题,自己到MSDN去好看看类继承之间的关系
      

  2.   


    这里只是声明变量a是A类,于是编译器在编译随后的代码时就允许a变量可以引用任何兼容于a类的对象,例如B的子类也是兼容于A类。
      

  3.   

    可以理解为 a 是个披着 A 皮的 B
      

  4.   

    可以引用任何兼容于a类的对象  -->  可以引用任何兼容于A类的对象这是多态的基本概念,也是面向对象与结构化编程的最基本的区别之一。
      

  5.   

    a 还是A类,只是你将 a=b了,我觉得上面有个人将得很好, a是披着A皮的B类
      

  6.   


    楼主,我来给你分析一下代码: A a = b; 这个a到底是A类的还是B类的啊? LZ, 里面的 a 是A的 声明 类。 懂? 因为B类是继承A类的,代码很明显, 它首先 B b = new B();这样,B声明了一个b的声明类,而实现类也是B本身(NEW B()), 所以下面代码 A a = b;其实也就是B是实现类,所以打印a.F的时候,调用的B本身,也就是这个方法啦: new public void F()
       {
       Console.WriteLine("B.F");
       }所以打印出来的是方法里的B.F
    我们再来分析一下a.G 打印出来的为什么是B.G?
    看代码: 因为小 a 是 A的声明类,所以,而且调用的是a.G这个方法,并没有接实现类,所以这个方法调用自己本身。但。LZ,请仔细看,A类里面的这个方法:  public virtual void G()
       {
       Console.WriteLine("A.G");
     
    很明显它是虚方法。定义了关键字Vritural, 因为B类是继承A类的,我们还要再来看B类的G()方法:  public override void G()
       {
       Console.WriteLine("B.G");
     
    很明显的,对A类的G方法进行了重写,它用了overiride关键字对A类 G 的方法进行重写了。SO。。打印出来的结果很自然的就是 B.F  和 B.G 了,LZ,懂吗? 不懂,欢迎继续追问。
      

  7.   

    因为对A类的 G 方法 进行了重写,所以调用的就是 B 类的G方法了。打印出来的 结果也 就是B.G了.不知道,这样说 LZ 是否明白? 不明白欢迎 LZ 继续 追问。
      

  8.   

    lz根本不理解继承。继承就是类型的具体化。实际上不是它是B,又可以伪装成A,或者它是A又附加上B。而是,它是A,具体来说,它是B。这好比,你是人,也是中国人。人和中国人不是两回事,中国人就是人。不存在中国人必须披着人皮才算人,否则还不算中国人了。或者中国人可以剖开身体,从肚子里面掏出一个叫“人”的东西。中国人和人,说的都是同一回事。
      

  9.   

    楼主,你能确认a.F()显示的是B.F?
      

  10.   

    B派生于A,一个B的实例化对象b指向了A类的变量a,但是a只能访问b中的基类部分的字段,属性和方法,无法访问派生类的字段,属性和方法,除非是virtual和override标记的.
    显然,A.F()将执行A类中的F()
    a.F()将显示A.F
      

  11.   

    b.F() and b.G() 没有什么疑问吧,你可能问题是出在 a.F() and a.G()。
    a.F() 会找它实际 new 的对象的 F() 方法,但是发现 B 类的 F() 方法被 new 了,所以他往上按照继承线搜索,找到第一个没有被 new 过的继承下来的方法。
    a.G() 没什么,G() 被重写,而且 a 变量指向的又是 B 类的对象,所以就调用 B 类的方法 G()。
      

  12.   

    A类中的F()方法并不是虚方法(virtual),所以a对象只会执行A类的F()方法,和B类的F()中的new没有关系.即使B类F()定义时没有加New,a.F()也只会执行A类的F()方法.至于B类中F()方法定义时加入new关键字完全是为了消除编译器的警告.
      

  13.   

    B b = new B();
      A a = b;
    主要是这两句话,看第二句,把b方法付给了a  所以后面引用到的都是在a里的
      

  14.   

    这个 A a =b可以解释为:   “a是A,具体的来说a是B”a是水果,具体来说,他是个苹果。
      

  15.   

    a.F()显示的是应该是A.F吧?测试显示a.F()显示A.F而不是B.F
      

  16.   

    打印出的结果是:A.F
                    B.F
                  B.G
                  B.G
    在多态对象中,调用隐藏方法时,调用的是父类的方法;
              调用覆盖方法时,调用的是子类的方法;
      

  17.   


    LZ,不好意思,看错了。我勒个去。a.F() 这个方法 打印出来的应该是 A.F才对,因为:A a = b;
    a.F();思路还是没错的,a 是 A 的声明类,b是实现类。 b并没有 实例化 对象。 在来看看 A 类的 F 的方法,子类并没有进行重写。所以调用 的应该是 A 类 自身的 F 方法才对。所以打印出来的是 A.F 才对。靠一失足 成千古恨啊。 LZ,不懂的欢迎继续 追问。最后 打印 出来的 四个 结果是: A.F  B.F  B.G  B.G。
      

  18.   

    大家说得好,但没有多少人象楼主这样搞的,这样搞容易误会。  但在装箱,拆箱却用得到,但不是用父类名,而是用根父类名[object]你看下面的代码就知到了:
    //《1》
      int i = 10;
      object obj = i;//你说obj 不就是10吗。
    //《2》
      object  obja =  new A();//obja 又是什么?
    //《3》
      object o;
      A a = new A();//[A]
      B b = a;
      o = b;//你说为是什么? 不就是 (//[A])在这里创建得吗。
      

  19.   

    求高手指点下,,  
    new public void F()
      {
      Console.WriteLine("B.F");
      }这个new表示什么?
    我是初学者.
      

  20.   


    我知道是的,B 类中 这个new 的这个函数 表示 对基类 A 的同名函数复盖。
      

  21.   


    没错,楼上解析的不错。 虽然是New了,但并没有对这个 方法 进行 重写。
      

  22.   

    那就是这里面的a 只能访问,基类A中的方法了啊?
    还有个问题就是我看了个帖子说的是,
    序号  基类(A)中是否有virtual 子类(B)中是否有override 输出(B输出)
    1    是                         是             B.G
    2    是                              否             B.G
    3    否                              是             编译错误
    4    否                              否             B.G请问下这样总结对不对啊 谢谢大家的热心帮助。
      

  23.   

    真没想到这个问题引来了这么多回复。
    你可以记住这么多规则,然后去使用,比如多态。
    如果你要追根问底,就要去看看CLR是怎么调用实例方法,虚方法(抽像方法本质上也是虚方法),静态方法的。当你理解了这些工作机制,这些问题就迎刃而解了。
      

  24.   


    楼主,你首先得理清概念先。看看父类是不是虚方法或者抽象方法(Vritural或Abstract)。 子类有没对父类的方法进行重写(Override),重写了,就对父类的方法就有影响了。
      

  25.   

    我晕,差点改变我一直认为的东西,a.F();明显应该打印A.F
      

  26.   

    看看CLR相关的东西就明白了A a=b;
    a.F();调用的谁,这就看就掌握一个就近原则。
    A a只是声明 了一个A类型的指针,其实实体是b.
    搞清楚b是个什么类型的东东就OK了嘛。
      

  27.   

    我基类用了Vritural,子类没有用Override,这样到底显示的是继承的基类的值还是子类的值,我在网上看到了不一样的结果,我自己调试是,显示的是子类的, 子类用不用Override都是显示的子类的啊。
    基类不用 public void F(),子类也用public void F()  结果显示的也是子类的值, 这样感觉Override 没什么意义了啊,求解 谢谢大家
      

  28.   

    G()是个虚继承函数,F()是被覆盖从写了。a 有指向new B 所以就有了你的结果。
      

  29.   

    吓死爹了,打开帖子,觉得楼主看错了,override和new一个是虚函数,一个不是,怎么可能会一样?结果,下面一群人一本正经地解释,难道是我的错,害得我启动了一下vs,果然还是楼主看错了,晕。
      

  30.   


    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();
      }
    }昨天刚看了有关C#继承及多态的东西;对于LZ的问题我的理解如下:
    首先B b = new B();
        A a = b;
    这两行代码:声明了一个A类型对象的引用即a,一个B类型对象的引用即b;
    由于A,B之间存在继承关系,这样a,b之间存在赋值兼容性,故可以将一个B类型的变量(b)赋值给A类型的变量的引用。
    也即是说:a,b两个应用指向同一个对象(new B()这个对象).注意了这里值相同一个对象是有差别的:对于引用a,只有对象中的基类成分对它是可见的;而对于b,整个对象的所有成分对它都是可见的。这就解释了a.F();的执行结果为"A.F",B累中的F()方法对a不可见。
    下一个疑点:为什么a.G()执行的是B类中的G()方法呢?
    这就得理解一下virtual、override这两个关键字了:override的作用就是使基类的引用(即a)可以访问派生类中的同名成员(具体而言是相同的签名),而这个成员必须使用override关键字标注,同时基类中的同名成员使用virtual关键字来标注。可以这样理解:执行A.G() 时,本该调用A类中的G()方法,但A类中的G()方法前有virtual关键字,调用即转移到B类中的带override关键字的同名方法,所以最后执行的是B类中的G()方法,结果输出的自然是"B.G".
    不知道楼主看懂了我上面说的后,现在有没有搞懂;
    其实楼上也有的说到了B类中的F()方法加new关键字只是为了避免编译器的警告,LZ可以去掉那个new,执行结果将是相同的。
    说这么多,我觉得LZ最重要的是要理解new,virtual,override这几个关键字的用处
      

  31.   

    lz误导人啊我实际测试了下a.F();打印出来的是“A.F”。看上面有些人分析的这么辛苦。。
      

  32.   

    楼主给的问题都错了。
    a.F();a.G() 显示的是A.F B.G,而不是B.F B.G
    原因:
    1、a.F()是非虚方法,是被b.F() new的,所以调用a.F()的时候不会执行b.F();
    2、a.G()是虚方法,是被b.G()override的,所以调用a.G()的时候,会执行b.G().
    这就是new和override的区别,也是多态的精髓。
      

  33.   

    楼主给的问题都错了。
    a.F();a.G() 显示的是A.F B.G,而不是B.F B.G
    原因:
    1、a.F()是非虚方法,是被b.F() new的,所以调用a.F()的时候不会执行b.F();
    2、a.G()是虚方法,是被b.G()override的,所以调用a.G()的时候,会执行b.G().
    这就是new和override的区别,也是多态的精髓。
      

  34.   

    就是就是  楼主写错了吧public new F(){}这样吧
    而且这个执行的应该是A的方法
      

  35.   

    1、A和B两个类有继承关系,但两个类中F方法没有任何关系,实现各自不同的逻辑。2、当调用a.G()方法时,由于该方法是虚方法 ,按照继承链的调用规则,首先调用继承得最远的那个方法也就是B中的G,所以执行Console.WriteLine("B.G");
      

  36.   

    定义一个人类(Person类),该类中包含两个字段name,age。再定义一个学生类(Student类),它是Person类的派生类,该类中包含学号、英语成绩、数学成绩、语文成绩等字段。包含两个方法(方法名自定),一个方法的功能是计算总成绩并输出;另一个方法的功能是根据总成绩判断是否升学,总成绩>=200分时显示可以升学,否则显示不可升学。
    在主函数中新建若干个student类的对象(四个以上),分别以学号,姓名,年龄,各科成绩作为参数。并分别调用上述的两个方法。
    急求帮助。明天考试要用。