C#陷阱之构造函数调用虚方法

  先说问题描述,现在有一个Test的类,其信息如下:

class Test
 {
        public string info = "测试类的成员";
 }
定义一个人类的类信息:

class Person
    {
        //声明一个Test的变量引用
        Test test = null;
        public Person()
        {
            if (null == test)
            {
                test = new Test();

                Console.WriteLine(Say());
            }
        }
        public virtual string Say()
        {
            return string.Format("这是人类类的{0}", test.info);
        }
    }

定义一个Man类,继承了人类类,并且对虚方法进行了重写:

class Man : Person
    {
        Test test = null;
        public Man() : base()
        {
            if (null == test)
            {
                test = new Test();
            }
            Console.WriteLine(Say());
        }
        public override string Say()
        {
            return string.Format("这是男人类的{0}", test.info);
        }
    }

现在在主方法进行如下测试:定义一个Person的对象

static void Main(string[] args)
 {
        Person p = new Person();

        Console.ReadKey();
  }
输出结果为:

接下来,初始化一个Man类的对象:

static void Main(string[] args)
        {
            Man m = new Man();

            Console.ReadKey();
        }
结果运行起来报错了:

说明对象为空时候进行了调用,下来我们看看报错的信息具体位置

在Man类中的重写Say方法中报错了,说Man类中的test没有被实例化。

这个时候,我想了想无论从哪里看都好着啊,怎么会这样啊?明明在构造函数里面初始化对象了?怎么会是空呢?

单步调试,设置断点,调试中发现,Man类继承Person类,在Main方法初始化Man类对象时候,根据继承规则,首先调用父类的构造函数,执行父类构造函数初始化test变量,并且调用Say这个虚方法,但是当执行到调用虚方法时候直接跳到子类Man中执行进行重写的Say方法,这时候,子类的test变量还没被初始化,因为父类构造函数没有执行完,子类还没有调用到构造函数,所以没有实例化子类的test成员,进而使用test.info时候,运行时报错。

这里就是一个陷阱,解决办法只有一个,说了感觉跟没说一个样,就是不再在子类的构造函中间接或者直接的调用虚方法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值