本帖最后由 Vurteon 于 2014-03-26 18:54:14 编辑

解决方案 »

  1.   

    子类继承父类然后重写方法,使用父类的引用调用子类重写过的方法确实会产生多态,按照其方法表的观点来看
    就是调用了覆盖了从父类继承来的指针,由RTTI来确保转型正确。
    但是,如果像上面的代码,唯一能解释的就是,子类知道自己重写了父类的方法,主动的在运行时覆盖了父类方法
    表中的指针,使父类的方法指针指向子类重写的方法,但是不确定这个是否是正确的。不知到背后的原理到底是什么?
      

  2.   

    问题解决,Java在构造对象的时候,其方法调用是由子类向父类延伸,而不是从父类开始向下查找。开始的猜测是错的,这样就可以按照方法表的方式解释了。唉,漏掉了这么基础的知识才会出现这样的迷惑啊!
      

  3.   

    Java编程思想中的,原话是“一个动态绑定的方法的调用却会向外深入到继承层次的结构内部”,个人觉得那个“向”应该写为“从”,这样,由于子类重写了方法,所以其方法表中便会是指向这个新的重写的方法的指针而不是指向父类的那个方法,便会调用子类自己的方法了。这种类初始化由上到下,而方法调用由下到上会带来一些问题,实际中不要有我说的这种写法。
      

  4.   

    Java编程思想中的,原话是“一个动态绑定的方法的调用却会向外深入到继承层次的结构内部”,个人觉得那个“向”应该写为“从”,这样,由于子类重写了方法,所以其方法表中便会是指向这个新的重写的方法的指针而不是指向父类的那个方法,便会调用子类自己的方法了。这种类初始化由上到下,而方法调用由下到上会带来一些问题,实际中不要有我说的这种写法。
    或许是翻译的错!
      

  5.   

    子类构造时会先调用父类的构造方法,当然是调用了父类的test()方法
      

  6.   

    首先是子类的构造函数继承了父类的,所以可以调用test方法,然后因为子类重写了父类的test的方法,new子类对象的时候,会调用子类test方法,实现多态,所以打印的是why??
      

  7.   

    多态的范围很广,详细可以参考这篇文章
    http://developer.51cto.com/art/201009/225990_all.htm
    这样回答太过于
      

  8.   

    http://blog.csdn.net/ns_code/article/details/17965867
      

  9.   

    看这个 http://blog.csdn.net/ns_code/article/details/17965867
      

  10.   

    Test是在构造函数里调用的,此时对象的虚函数表还没有建立起来,即对象还没有完全构造完,此时调用此对象自己的函数,即ExtendBase的Test函数。
      

  11.   

    Java的表区具体的我现在还不太明白,但是你说这个即使是在C++里面也是有问题的。
    你可以参考下面的文章。
    http://www.cppblog.com/dawnbreak/archive/2009/03/10/76084.aspx
      

  12.   

    这样理解
    子类重写了test方法
    继承了构造方法
    然后你调用的时候是new的子类
    所以是用的子类的test方法
    因为继承了父类的构造方法
    所以会执行test方法
      

  13.   

    java中所有的函数默认都是虚函数...这是和C#不同的地方之一
      

  14.   

    new 一个对象时要先构造父类,但是test()被覆盖了,调用的是子类的test()。package test;import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
     
    public class TestTime {     public static void main(String[] args) {
            //创建子类对象
            new extendsBase();
            new Base();
        }
     
     
    }
    class Base{
        public Base(){
            test();
        }
        public void test(){
            System.out.println("Base!");
        }
    }
     
    //继承Base,重写test方法
    class extendsBase extends Base{
        @Override
        public void test() {
            System.out.println("in children");
        }
        public extendsBase()
        {
         System.out.println("in children ctr");
        }
    }输出结果:
    in children
    in children ctr
    Base!
      

  15.   

    就C++而言new extendsBase的时候,先调用的Base的构造函数,而Base的虚表中test指向的是子类的方法。这就是多态。
    在构造函数中调用虚函数不是个很好的习惯,如果extendsBase的test使用extendsBase的变量呢?变量是有的,但没有初始化呀。
      

  16.   


        public class Problem {
            public static void Main(String[] args) {
                //创建子类对象
                new extendsBase();
                Console.ReadLine();
            }
        }
     
        class Base{
            public Base(){
                test();
            }
            public virtual void test(){
                Console.WriteLine("Base!");
            }
        }
     
        //继承Base,重写test方法
        class extendsBase : Base{
            public extendsBase():base() //注意此处显示的调用父类的构造函数,但输出结果仍然是:Why????
            {
            }        public override void test() {
                Console.WriteLine("Why????");
            }
        }我们再看另一种情况,输出就是Base!:public class Problem {
            public static void Main(String[] args) {
                //创建子类对象
                new extendsBase();
                Console.ReadLine();
            }
        }
     
        class Base{
            public Base(){
                test();
            }
            public  void test(){ //此处我把virtual 关键词去掉了
                Console.WriteLine("Base!");
            }
        }
     
        //继承Base,重写test方法
        class extendsBase : Base{
            public extendsBase():base()
            {
            }
           //由于父类存在一个test方法,那么在C#中函数前面不加new关键词的话,是编译不过去的。
           //这是java虚函数和C#实体函数的区别
            public new void test() {  
                Console.WriteLine("Why????");
            }
        }
    其实你的代码,就等同于上面第一种情况的代码是一样的!不知道能不能给你一点思路
      

  17.   

    应为调用了父类Base 的构造方法,而Base 的构造方法有test()方法,test方法被子类复写,改成了System.out.println("Why????");,所以输出why了
      

  18.   

    默认的构造函数  就是  类名() {   super();   }
      

  19.   

    Java的表区具体的我现在还不太明白,但是你说这个即使是在C++里面也是有问题的。
    你可以参考下面的文章。
    http://www.cppblog.com/dawnbreak/archive/2009/03/10/76084.aspx
    ----------------------------------------------------------------------------------------------------------------------
    我的意思是对象构造函数里最好不要有虚函数。因为构造期间,虚函数表是没有建立起来的,对象只能调用自己的函数,而不是虚函数表里的函数指针。
      

  20.   

    每一个对象都有自己的方法表,由于子类继承父类,所以在new子类对象的时候,子类默认构造器会调用父类的无参构造器。
    由于子类重写了父类的test方法,所以子类的方法表中存的是重写之后的test方法的地址,所以调用子类重写之后的test方法