现在解释上面两个会出错的原因,这个原因是动态性的根本所在。
我尽力能解释清楚一点。
**************关键一********************
因为父类和子类的对象在内存中的大小是不一样的,当然了不同的对象本身就不可能是同一块内存地址的。
这个应该没有问题的吧,当然了要是子类中只是简单的继承而没有都没有做的话,可能是一样的,但是在c++中各家编译器还有会有一点差异的,可能也会不一样的。
***************关键二************************
引用本质上是通过指针来实现的,更深入一点是引用是指向指针的指针,而不同类型的指针所管理的内存空间大小是不一样的,这一点跟上面联系很紧的。注意这里是说指针管理的内存而不是指针,我想大家都
知道指针只有4个字节长度的。这里我们可以简单的说是变量的可见性问题,因为变量虽然存在但是并不一定是可见的。
***************关键三************************
多态性的关键是动态绑定,说白了就是虚拟函数虚拟指针虚拟指针表等几个重要的概念。简单讲一下,这里很复杂的,但是每一个真正的面向对象编程人员必须花时间很好的理解这一点。java 中只有静态函数和虚拟函数两种,c++中还有一种 非静态非虚拟函数。所以java的动态绑定要容易一点的。 你可以不精确的这样理解(因为解释精确我也很懒,可以写很长的文章了),每次类编译的时候都会生成一个虚拟函数表,表里面保存自己类中所有的虚拟函数地址,同时要是这个类存在父类 (不管是extends class 还是implements interface)的话,同时他会把从父类继承来的虚拟函数表也继承过来(这里我只是大概解释,不是很准确)。
这个地方请注意:
************************************************
要是子类没有改写父类继承的方法,父类虚拟函数中对应虚拟函数地址被变成子类自己的虚拟函数地址;如果没有改变则不需要改变继承来的虚拟函数表对应函数的地址。
*************************************************
***************开始解释************************
当父类引用指向子类对象的时候,父类引用管理的内存空间,是要比子类真实的内存空间小的。所以子类中比父类中多的东西对于这个父类引用来说是不可见的。所以也就没有办法引用。
上面的那个变量引用和函数引用就是这样的,因为父类中没有变量ageOfTest和函数display2()的。但是我们可以知道父类指针实际上是指向子类的,所以我们解决这个问题的方法就是:强制转换类型(java中叫造型)。
同时可能有人要问,子类中那个函数地址不是也在虚拟函数表中吗?很高兴你问这样的问题,但是父类引用看到的虚拟函数表是没有那个函数项目的,因为他对于父类引用绝对是不可见。
对于另外一个虚拟函数调用,如果你看了说明很仔细的话,你现在一定知道虽然是父类引用管理内存范围小,但是那个虚拟函数表,父类中有的,但是由于函数被子类中改写了,所以那个表中函数地址编程子类的拉,当然就是引用子类的方法了。
/****************重要补充************************
java中静态函数是没有动态性,因为静态函数不能被继承,也不能被改写为非静态方法。因为静态就意味着类的所有实例共享一个实体。
&nbs