一个古老的面试题给我们的思考

来源:互联网 发布:js如何给对象添加属性 编辑:程序博客网 时间:2024/05/16 17:07

 写出程序的输出结果:
public class A 
{
        public virtual void Fun1(int i)
       {
            Console.WriteLine(i);
        }

        public void Fun2(A a)  
       {
            a.Fun1(1);
            Fun1(5);
        }
}


public class B : A 
{
        public override void Fun1(int i)   
       {
            base.Fun1 (i + 1);
        }

        public static void Main()  
       {
            B b = new B();
            A a = new A();
            a.Fun2(b);
            b.Fun2(a);         
        }
}
结果是2,5,1,6。
这是一个很古老的面试题,我当时在一家公司面试时也遇到了这个问题,当时我的结果是1,5,2,5。也就是最后一个错了,就这个问题
引起了我的思考,我觉得我在写程序时忽视了一个很重要的问题。那就是单步调试的作用。
其实我们应该在写程序时经常用一下单步调试
,这样能让我们能更好地理解程序的执行过程,这样就不会像很多网友说的做这个题做的头疼。那么现在来分析一下这个题目吧,
  程序首先从Main()执行;——>B b = new B();如果B中有构造函数就再去执行它。——>A a = new A();如果A
中有构造函数就再去执行它。——>a.Fun2(b);到这时A中的public void Fun2(A a)把b传进去就得到b.Fun1(1);Fun1(5);程序就再跳到
B中public override void Fun1(int i)得第一个结果2,再执行Fun1(5);跳到A中public virtual void Fun1(int i)得第二个结果5
那么a.Fun2(b);就执行完了。再执行b.Fun2(a);程序又会在基类中找到public void Fun2(A a),得到a.Fun1(1);Fun1(5);
就会执行a.Fun1(1)得到结果1,最后一点要注意,我先也错过,这里Main()中是b.Fun2(a);所以会跳到B中执行public override void Fun1(int i)
得到结果6。所以结果是:2,5,1,6
所以我们在写程序时不要想当然认为程序会怎么执行,我们分析程序结果时一定要了解程序的执行过程,这样就灰觉得很简单
那么我们不妨在写完每一个程序后都看看它的执行过程。这样我们能更清楚地了解程序。
留个问题给大家吧:
public abstract class A 
{
        public A() 
       {
            Console.WriteLine('A');
        }
        public virtual void Fun() 
       {
            Console.WriteLine("A.Fun()");
        }
}

public class B: A 
{
        public B()
       {
            Console.WriteLine('B');
        }

        public new void Fun() 
       {
            Console.WriteLine("B.Fun()");
        }

        public static void Main() 
       {
           A a = new B();
           a.Fun();
        }
}

看看程序时怎么执行的,是先调用A的构造函数还是B的呢?