zoukankan      html  css  js  c++  java
  • 在基类构造器中调用虚方法需谨慎

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

        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

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

  • 相关阅读:
    Android pm命令用法
    SSH没有password安全日志
    使用reserve要再次避免不必要的分配
    找到最大的迭代次数串
    个人存储不同类型的对象有一些想法的碰撞检测
    [Android 4.4.3] 泛泰A870 Mokee4.4.3 20140610 RC2.0 通过刷第三版 by syhost
    zoj 3823 Excavator Contest(结构体)
    【Linux】CentOS系统
    Swift学习——Swift解释特定的基础(七)
    Android JNI开发提高篇
  • 原文地址:https://www.cnblogs.com/darrenji/p/4112092.html
Copyright © 2011-2022 走看看