不明白为什么调用子类的方法?

backham2000 2008-07-28 08:46:26
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()方法,怎么会调子类的重写方法?
请详细解释
...全文
101 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Adechen 2008-07-29
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 ivorstar 的回复:]
如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。
如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不是调用基类方法。
[/Quote]
bwangel 2008-07-29
  • 打赏
  • 举报
回复
你明明在main函数里声明的是B对象而不是A的对象,为什么要调用A的方法?

你声明个A对象试试?
luofuxian 2008-07-29
  • 打赏
  • 举报
回复
学习,我也晕晕的
virusswb 2008-07-29
  • 打赏
  • 举报
回复
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
moonsliver 2008-07-29
  • 打赏
  • 举报
回复
那个。。。如果B继承A,C继承B
只有new C()的时候,在A的构造函数中调用PrintFields 才会有三种选择
否则仅仅new B()的话,还是只有两种选择的。。。

为什么不能修改自己的回复呢?=。=
moonsliver 2008-07-29
  • 打赏
  • 举报
回复
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();

结果将会和上面一样。
backham2000 2008-07-28
  • 打赏
  • 举报
回复
我觉得这里边还有一个对象的问题,
这是声明的B的对象调用的是这个结果
如果声明A的对象,
调用的就是类A 的virtual 方法

好像明白点了,又好像晕晕的
moonsliver 2008-07-28
  • 打赏
  • 举报
回复
代码运行到:

public A()
{
PrintFields();
}


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

楼主可以尝试将B的override去掉,这样调用的就是类A的PrintFields方法了
backham2000 2008-07-28
  • 打赏
  • 举报
回复
程序的执行应该是下面的流程

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

难道声明了B的对象,连A的构造函数的对象都是B,所以
才能调用B的方法PrintFields(),我晕了
backham2000 2008-07-28
  • 打赏
  • 举报
回复
程序的执行应该是下面的流程

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

难道声明了B的对象,连A的构造函数的对象都是B,所以
才能调用B的方法PrintFields(),我晕了
backham2000 2008-07-28
  • 打赏
  • 举报
回复
子类重写的调用自己的是对的,
我不明白的是加重字体的下面这段
public A()
{
PrintFields();
}

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

amandag 2008-07-28
  • 打赏
  • 举报
回复
因为PrintFields()被子类重写了,面向对象的基本概念,楼主要多看看书
ivorstar 2008-07-28
  • 打赏
  • 举报
回复
这就是oo中的多态性啊,override修饰符重写了父类的方法,所以obj对象的真实类型是B,就会调用B中的方法。如果用new的话就会调用自己的那个virtual方法,注意一下override和new的区别:
如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。
如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不是调用基类方法。
backham2000 2008-07-28
  • 打赏
  • 举报
回复
怎么没人回复啊?

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧