收录日期:2020/10/31 20:50:14 时间:2016/07/04 16:42:43 标签:C#
 class Program
    {
        static void Main(string[] args)
        {
            B obj = new B();
            obj.PrintFields();
           
        }
    }

 
     class A
     {
          public A()
           {
                PrintFields();
           }
          public virtual void PrintFields(){}
      }
    class B : A
    {
        int x = 1;
        int y;
        public B()
        {
            y = -1;
        }
        public override void PrintFields()
        {
            Console.WriteLine("x={0},y={1}", x, y);
        }
    }
}

这个程序的执行结果是 X=1,Y=0;x= 1 y = -1

有个关键的地方,就是类A中构造函数调用的方法PrintFields()为什么是子类的?不是那个自己的virtral方法?
我觉得它应该调自己的virtual PrintFields()方法,怎么会调子类的重写方法?
请详细解释
怎么没人回复啊?
这就是oo中的多态性啊,override修饰符重写了父类的方法,所以obj对象的真实类型是B,就会调用B中的方法。如果用new的话就会调用自己的那个virtual方法,注意一下override和new的区别:
如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。
如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不是调用基类方法。
因为PrintFields()被子类重写了,面向对象的基本概念,楼主要多看看书
子类重写的调用自己的是对的,
我不明白的是加重字体的下面这段
public A()
          {
              PrintFields();
          } 

这是类A的构造函数,调用的理应是类A的virtual方法,
但实际他调用的是子类B的方法
不理解

程序的执行应该是下面的流程

类A的构造函数A()
类B的构造函数B()
类B中的方法PrintFields()

难道声明了B的对象,连A的构造函数的对象都是B,所以
才能调用B的方法PrintFields(),我晕了
程序的执行应该是下面的流程

类A的构造函数A()
类B的构造函数B()
类B中的方法PrintFields()

难道声明了B的对象,连A的构造函数的对象都是B,所以
才能调用B的方法PrintFields(),我晕了
代码运行到:

public A() 

    PrintFields(); 



由于类A的PrintFields是虚方法,所以在实际调用方法PrintFields前,会先判断A的子类有没有重写(override)
这个方法,如果有的话就调用子类的方法,没有,才决定调用的是类A的PrintFields方法

楼主可以尝试将B的override去掉,这样调用的就是类A的PrintFields方法了
我觉得这里边还有一个对象的问题,
这是声明的B的对象调用的是这个结果
如果声明A的对象,
调用的就是类A 的virtual 方法

好像明白点了,又好像晕晕的
new。。。貌似就是在托管堆上根据指定的类型创建了一个存储空间。。。可以把它看成一块地。

B obj = new B(); 

这个时候,相当于根据B的大小以及其父类的大小,在这块地上画一块范围,也就是B+A的面积。。。

而代码

public A() 

    PrintFields(); 


将其更改为:

public A() 

    this.PrintFields(); 


调试的时候会发觉,this的类型是B,所以调用这个PrintFields方法的时候,就有两个选择,用A的或者用B的,之所以会有两个选择,是因为A的PrintFields方法是虚的,同时B也实现了这个方法,由于当初画地的时候,连A带B一起画了,所以才会有两个选择,所以假设B有子类C,而C也override了PrintFields方法,那么在代码运行到构造函数的时候将有3个选择。。。

而选择优先使用B的override的PrintFields方法,所以这里将调用B的PrintFields方法。

而代码

obj.PrintFields(); 

由于Obj的类型是B,所以调用的肯定是B的PrintFields

如果main将代码变成

A obj = new B(); 
obj.PrintFields(); 

结果将会和上面一样。
那个。。。如果B继承A,C继承B
只有new C()的时候,在A的构造函数中调用PrintFields 才会有三种选择
否则仅仅new B()的话,还是只有两种选择的。。。

为什么不能修改自己的回复呢?=。=
class Program
    {
        static void Main(string[] args)
        {
            B obj = new B();
            obj.PrintFields();
         
        }
    }


    class A
    {
          public A()
          {
              PrintFields();
          }
          public virtual void PrintFields(){}
      }
    class B : A
    {
        int x = 1;
        int y;
        public B()
        {
            y = -1;
        }
        public override void PrintFields()
        {
            Console.WriteLine("x={0},y={1}", x, y);
        }
    }

是类初始化顺序你没有高明白了
先是基类的构造函数,然后是继承类的构造函数
这里先是a的构造函数,调用PrintFields();,但是a的PrintFields();是虚拟的,什么都没有做,然后调用他的实现方法,就是b的PrintFields();,显示x,y,这时候x是初始化为1,y没有初始化,默认0,所以显示x=1,y=0。
然后构造b,调用b的构造函数,把y初始化为-1.然后是 obj.PrintFields();这句,调用了b的PrintFields()方法,显示x和y,这是后x没有变,y在b的构造函数中赋值-1
所以显示的时候就是x=1,y=-1
执行结果是 X=1,Y=0;x= 1 y = -1 
学习,我也晕晕的
你明明在main函数里声明的是B对象而不是A的对象,为什么要调用A的方法?

你声明个A对象试试?
引用 2 楼 ivorstar 的回复:
如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。 
如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不是调用基类方法。 

动态创建控件的事件怎么获取 难度很大的问题:用asp读取网卡MAC地址 在Web应用程序与Windows form中如何调用Web service中的类呢? 关于日文乱码的问题,请进 !!我kao,斜了门了,巨郁闷,Blt与BltFast的问题,请大侠指教 ps/2口問題 我想对一个表用以下方法做一个循环,但就是不行 那位兄弟告诉我一下怎么建立一个XML文件 (初学):在窗口中输出文字 找优秀的数据库开发人员 急!实现如同.net中工具栏那样的东东该用什么控件? 在线请教一个关于标准C的字符串问题: 我想开发一个基于web的办公平台,应该用web appliction还是用web services好呢 失恋了散分 哪里有DB2 Development Center 下载啊? 配置innodb的问题 读硬盘的ID号的函数是什么啊 谁能实现这样的打印????高分相送!! 我是java初学者,请教高手!在线等! 请教公有地址与私有地址访问问题 高手请进,低手莫入,搞分相送 对你非常简单的问题:Windows编程初步 急!USB调试 java.library.path是什么东西? 如何在每个输入框中通过打回车键,进行切换呢 水源的兄弟门,我做销售拉,好爽啊,第一天我就提了3000块。 与手机通讯,除计算机和手机外,还有与手机相配的串口数据线,请问这根数据线买手记的时候为什么没有给?要自己另外买吗? 怎样实现多个子窗体间的相互切换? 啊有什么办法可以让日期显示为2003-01-01,月日都占两位,不足补0 关于如何生成word/excel/pdf文件