在基类构造器中调用虚方法需谨慎_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 在基类构造器中调用虚方法需谨慎

在基类构造器中调用虚方法需谨慎

 2014/11/21 10:55:07  Darren Ji  程序员俱乐部  我要评论(0)
  • 摘要:最近,在基类的构造函数中调用虚方法时,发现了一个问题。先把问题重现如下:classProgram{staticvoidMain(string[]args){varc=newChinese(18);Console.ReadKey();}}publicclassPeople{publicintAge{get;protectedset;}protectedPeople(){this.Say();}publicvirtualvoidSay(){Console.WriteLine(string
  • 标签:方法 构造 谨慎 构造器

最近,在基类的构造函数中调用虚方法时,发现了一个问题。先把问题重现如下:

monospace; width: 100%; margin: 0em; background-color: #f0f0f0">    class Program
    {
        static void Main(string[] args)
        {
            var c = new Chinese(18);
            Console.ReadKey();
        }
    }
    public class People
    {
        public int Age { get; protected set; }
        protected People()
        {
            this.Say();
        }
        public virtual void Say()
        {
            Console.WriteLine(string.Format("基类说我今年{0}岁了", Age));
        }
    }
    public class Chinese : People
    {
        public Chinese(int age)
        {
            this.Age = age;
        }
        public override void Say()
        {
            Console.WriteLine(string.Format("子类说我今年{0}岁了",Age));
        }
    }

 

运行以上的代码,结果会是以下两种情况之一吗?
基类说我今年18岁了
子类说我今年18岁了

 

都不是!而是:
1

 

为什么?
→调用子类构造函数new Chinese(18)
→先调用父类无参构造函数,并调用虚方法Say
→发现虚方法Say重载,就调用子类ChineseSay的重载,但此时子类Chinese还没有对Age属性初始化,此时的Age属性值为默认值0


如何避免呢?
--去掉在基类构造函数中调用虚方法的代码
--用子类实例调用重载方法

 

    class Program
    {
        static void Main(string[] args)
        {
            var c = new Chinese(18);
            c.Say();
            Console.ReadKey();
        }
    }
    public class People
    {
        public int Age { get; protected set; }
        protected People()
        {
        }
        public virtual void Say()
        {
            Console.WriteLine(string.Format("基类说我今年{0}岁了", Age));
        }
    }
    public class Chinese : People
    {
        public Chinese(int age)
        {
            this.Age = age;
        }
        public override void Say()
        {
            Console.WriteLine(string.Format("子类说我今年{0}岁了",Age));
        }
    }

 

2

 

总结:当在基类构造函数中调用虚方法需谨慎,因为当父类调用虚方法重载的时候,子类还没有被初始化,可能会涉及到一些成员还未被初始化。

发表评论
用户名: 匿名