关于类、继承、抽象方法、构造函数等求输出结果的一些面试题
有好多面试的时候写几个类互相继承,里面有抽象方法,然后各种实例化,搞的晕头转向的,在这里稍微总结下,以后慢慢地补充:
1:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class A 2 { 3 public A() 4 { 5 6 PrintFields(); 7 } 8 public virtual void PrintFields() { } 9 } 10 class B : A 11 { 12 int x = 1; 13 int y; 14 public B() 15 { 16 y = -1; 17 } 18 public override void PrintFields() 19 { 20 Console.WriteLine("x={0},y={1}", x, y); 21 } 22 }
当使用new B()创建B的实例时,产生什么输出?
这个应该算是简单的,但是也有很多对于继承构造函数的执行顺序不清的弄得苦不堪言。
分析:
当new B()输出的为X= 1 ,Y = 0;
1、在new B()是会先调父类即A的构造函数,这时会执行PrintFields();方法,因为PrintFields方法为虚拟方法,在子类中重写的该方法,所在实际执行的为B中的PrintFields方法。
2、为什么Y=0?这是因在调用的是父类方法,子类的中的Y还没初始会,系统自己赋值为0。
2:
下面这一个问题是在第一个的基础上进行扩展下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class A 2 { 3 public A() 4 { 5 6 PrintFields(); 7 } 8 public virtual void PrintFields() { } 9 } 10 class B : A 11 { 12 int x = 1; 13 public int y; 14 public B() 15 { 16 y = -1; 17 } 18 public override void PrintFields() 19 { 20 Console.WriteLine("x={0},y={1}", x, y); 21 } 22 } 23 public class C 24 { 25 26 public static void Main() 27 { 28 B b = new B(); 29 Console.WriteLine("Y={0}", b.y); 30 Console.Read(); 31 32 } 33 }
分析:
答案为:X=1,Y = 0
Y = -1
至于为啥,各位打个断电调试下就知道了
3:
下面这个题各位不知道有没有犯迷糊的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 static Person GetPerson() 2 { 3 Person p = new Person(); 4 p.Age = 8; 5 try 6 { 7 p.Age++; 8 return p; 9 } 10 finally 11 { 12 p.Age++; 13 } 14 } 15 static int stac() 16 { 17 int i = 8; 18 try 19 { 20 i++; 21 return i; 22 23 } 24 finally 25 { 26 i++; 27 } 28 } 29 30 public static void Main() 31 { 32 Console.WriteLine(GetPerson().Age); 33 Console.WriteLine(stac()); 34 }
这个破题,真不知道该说啥了,直接公布结果:第一个为10,第二个为9
4:
上面的懂了,请看下一题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class A 2 { 3 public static int X; 4 static A() 5 { 6 X = B.Y + 1; 7 } 8 } 9 class B 10 { 11 public static int Y = A.X + 1; 12 static B() { } 13 static void Main() 14 { 15 Console.WriteLine("X={0},Y={1}", A.X, B.Y); 16 Console.ReadKey(); 17 } 18 }
答案是 1,2
看一下别人写的结论吧,我觉得说的听明白了,自己就不再多说了:
因为执行的时候,首先从程序的入口点(就是Main())找起,因为Main在类B中,所以从B类开始加载。执行顺序大致是这样的:
(用到一个类的时候是先对其静态变量初始化,然后调用他的静态构造函数)
(类的静态构造函数只在加载类的时候由系统调用一次且只此一次)
1.初始化B类的静态变量 Y,系统先给他一个默认值(此处是0),然后再执行他的初始化赋值语句public static int Y = A.X + 1;
2.执行这条语句的时候因为用到了A.X,所以遇到A的时候去加载类A,顺序一样,先是执行A的静态变量X的初始化工作public static int X;因为没有对其赋值的操作,所以X就是系统给他的默认值0;然后调用A的静态构造函数(B那里也是先初始化静态变量,然后才调用静态构造函数,因为B初始化静态变量的时候用到了A所以才会跳到A来,不然的话B那边也是初始化静态变量之后系统紧接着就会调用B的静态构造函数);
3,A的静态构造函数中执行X = B.Y + 1;可以知道,此时B.Y已经有了一个系统给他的默认值0,所以此处就是X=0+1;现在X就是1了
4,X那边都完工了,回到刚才跳转X的地方继续执行,就是继续执行Y = A.X + 1;毫无疑问此时是Y=1+1;至此,B的静态变量初始化完成了。
5,B的静态变量初始化完成了那紧接着就是系统调用B的静态构造函数,此处什么也不执行。
6.输出结果1,2