日期:2014-05-20  浏览次数:20947 次

c#面试题:继承与构造函数的调用
using System;
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);
}
当使用new B()创建B的实例时,产生什么输出?(20分)为什么?请详细说明(80分),谢谢

------解决方案--------------------
输出1,0

因为A必须在B之前构造,但x在调用B的构造函数之前已经赋值。



------解决方案--------------------
两种情况
(1) A a = new B();
这样的话,a.PrintFields()调用的是B的PrintFields方法,输出x=1,y=-1,因为使用B实例化a,所以调用B类的PrintFields方法;
(2) B b = new B();
这样的话b.PrintFields()调用的也是B的PrintFields方法,输出x=-1,y=-1,因为B的对象被B类实例化,调用的必然是B的东西;
(3) A a = new A();
这样调用的是A的PrintFields()方法,什么都不输出;
(4) B b = new A();
这样写是错误的,子类的对象不能被父类实例华。
------解决方案--------------------
探讨
两种情况
(1) A a = new B();
这样的话,a.PrintFields()调用的是B的PrintFields方法,输出x=1,y=-1,因为使用B实例化a,所以调用B类的PrintFields方法;
(2) B b = new B();
这样的话b.PrintFields()调用的也是B的PrintFields方法,输出x=-1,y=-1,因为B的对象被B类实例化,调用的必然是B的东西;
(3) A a = new A();
这样调用的是A的PrintFields()方法,什么都不输出;
(4) B b = new A();
这样写是错误的,子类…

------解决方案--------------------
答案是1,0. 因为X在调用B的构造函数时已经被赋上值了
------解决方案--------------------
X=1,Y=0,

应为在没跑public B() 

y=-1; 

之前先走到了public override void PrintFields() 

Console.WriteLine("x={0},y={1}",x,y); 

所以y=-1没有被赋值
------解决方案--------------------
只有一种情况,上面不要误导,怎么都是先跑 a的构造函数
------解决方案--------------------
构造方法的调用是从上到下的,所以在调用A构造方法时y的值还是默认的0,
A构造方法中调用的PrintFields已经被override所以最后输出 1,0
------解决方案--------------------
答案是1 , 0

最好的办法是跟程序理解
------解决方案--------------------
这段代码我运行过了,输出结果:

x=1,y=0
------解决方案--------------------
类B中y没有初始化,所以分配了值0给y; 
当B b = new B()时, 先调用父类A的构造函数,调用PrintFields(),由于PrintFields是virtual的,并在B中override,所以就调用B自己的PrintFields. 打印出x=0,y=1
------解决方案--------------------
输出x=1, y=0;
因为构造B之前,先执行变量,y没有明确赋值,默认为0。执行B的构造函数,因为B继承A,所以先执行A的构造函数。A构造函数调用的PrintFields方法在A类里是虚函数,它的实现是在B类,所以执行B类的PrintFields方法,结果输出。虽然继续执行完B的构造函数,使y的值是-1.但结果之前已经输出。
------解决方案--------------------
.net做了一些幕后的操作,如果是在C++中这样用的话,是会有问题的;

------解决方案--------------------
探讨
输出1,0

因为A必须在B之前构造,但x在调用B的构造函数之前已经赋值。




------解决方案--------------------
无非考的就是一个执行顺序而已:

1、实例化父类时,可以使用new子类,执行构造函数顺序为:先执行父类构造函数,再执行子类构造函数。

2、实例化子类时,执行构造函数顺序为:先执行父类构造函数,再执行子类构造函数(同上)
------解决方案--------------------
结果:x=1,y=0;
原因:初始化B的时候,会先初始化A的构造函数,之后调用A的方法,但因为方法是virtual,因此会调用B的重写方法。
此时B还未调用构造函数。因此输出如上。具体为何调用B的重写方法可以参考http://www.cnblogs.com/anytao/archive/2007/09/10/must_net_15.html
------解决方案--------------------