读书人

c#面试题:继承与构造函数的调用,该如

发布时间: 2012-02-19 19:43:39 作者: rapoo

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
------解决方案--------------------


认为只有一次输出的人都没搞清执行顺序
[解决办法]
搞清楚了.net的类初始化顺序:
类成员变量初始化先于类的构造函数
静态成员变量先于实例变量
子类成员变量先于父类成员变量
父类构造函数先于子类构造函数

[解决办法]
在创建一个类的实例的时候,是先创建一个唯一的父类,然后在父类的基础上构建其子类,C#中所有的类都是这样,当把一个子类实例赋给一个父类的变量名的时候
就像 B val = new A();
其实 val 还是指向父类的,并不是指向子类,(上面说了,先创建唯一的父类,并且父类和子类的并不是创建之后就脱离了关系)
当val调用了父类中的虚方法时,会自动调用子类中提供的方法(如果有的话)

额,个人观点,错了直接板砖伺候!

读书人网 >C#

热点推荐