与同事切磋java及C++,在多态这块困惑了事情其实是非常小小的:有父类Father及两个子类Boy,Girl。三类都是普通类,非抽象。有一公有函数test:
void test(),各自打印输出Father,Boy,Girl现在main中:
java:
Father f = new Father();
Boy b = (Boy)f;
Girl g = (Girl)f;f.test();
b.test();
g.test();问:先不要测试,输出什么?为什么?C++:
Father *f = new Father;
Boy *b = (Boy*)f;
Girl *g = (Girl*)f;f->test();
b->test();
g->test();delete f;问:这种情况下输出什么,为什么?最后请java及c++同时都是高手的高手来解答一下:
为什么会有这种区别?
void test(),各自打印输出Father,Boy,Girl现在main中:
java:
Father f = new Father();
Boy b = (Boy)f;
Girl g = (Girl)f;f.test();
b.test();
g.test();问:先不要测试,输出什么?为什么?C++:
Father *f = new Father;
Boy *b = (Boy*)f;
Girl *g = (Girl*)f;f->test();
b->test();
g->test();delete f;问:这种情况下输出什么,为什么?最后请java及c++同时都是高手的高手来解答一下:
为什么会有这种区别?
解决方案 »
- 常见的字符串解析抽取问题,40分,很简单的,大家过来看看
- 这里的多线程中的sleep方法为什么不能用?我加了try和catch,还是不行?
- java.lang.IllegalArgumentException: attempt to create saveOrUpdate event with null entity
- Parent Class(主类)和Child Class(子类)的疑问~!
- 新手提问:简单的字符串比较问题
- 谁提供一个swing的解决方案,谢谢咯...................嘿嘿
- java定时设计,每周,每月等
- 请高手帮忙
- 一个很简单JBuilder问题
- 一个java新手的问题
- 网络聊天与多线程问题
- 学校JAVA大赛项目问题
Boy b = (Boy)f;
Girl g = (Girl)f;
-----------
能这样强制转换?
Boy* b=new Boy;
Father*f=(Father*)b;
f->test();
这是如果你virtual void test()则会调用boy的test,如果void test()则会调father的test
2.父类引用指向子类对象
3.子类重写父类方法Father f = new Father();
Boy b = (Boy)f;
Girl g = (Girl)f;把你程序先修改一下再和你同事讨论多态...
多态调用的时侯,会跟据对象的getClass()来调用相应的方法。
Father f1=null;
Father f2=null;
f1=new Boy();
f2=new Girl();
Boy b=null;
Girl g=null;
b=(Boy)f1;
g=(Girl)f2;
父类引用f指向子类Boy
所以JAVA的应该全是Father吧;
C++的基类采用了指针对象,派生类的指针对象也指向了基类,这个输出我猜测是Father,Boy,Girl
Object可以强转为任何java类,莫名其妙
Father b = new Boy();
Father g = new Girl();
f.test() 结果为“father”;
b.test() 结果“boy”;
g.test() 结果“girl”;
Boy b = (Boy)f;
Girl g = (Girl)f;
不能这样转换的 自能讲父类转为子类 例如:
f = (Father)b;
java 与 C++;一样
如果不希望 virtual 在 Java 中需要明确设定成 final void test() 才行。void test() {}
C++中满足动态绑定,第一必须是指针,第二必须是虚函数,应该这样写,前提是test为虚函数
Father *f = new Father;
Father *b = new Boy;
Father *g = new Girl;
f->test();
b->test();
g->test();这样应该就会打印出来了
如果按你说的话,应该都会打印fatherjava:
Father f = new Father();
Father b = new Boy();
Father g = new Girl();
这个只是强制转换...不是多态...Father b = new Boy();
Father g = new Girl();实例化对象的时候至少要这个样子嘛...估计很多人都没把楼主的困惑搞清楚,或许是没把多态搞清楚,其实楼主的程序再修改一下能更好的说明这个问题。比如,我们又另外一个类,就叫OtherClass吧,里面有一个方法: myPrint(Father f){f.test()},OK,现在我们分别new两个类:Boy b = new Boy();
Girl g = new Girl();OtherClass o = new OtherClass();o.myPrint(b);
o.myPrint(g);这个样子大家认为输出的是什么呢?如果没有认识多态,可能认为输出的是father,因为myPrint方法里面是Father的引用啊...但是,正是有了多态的存在,这里打印出来的应该是boy和girl!这里可能很多人会疑惑,如果Father,Boy,Girl类里面各自有各自的String成员变量name,name各自赋值为"f","b","g"把myPrint方法再改一下
myPrint(){
f.name; f.test();
}这个样子打印出来可以看的很清楚,name永远是f,但是调用方法时,确实各自的boy和girl,这个是因为方法并不是和对象一样存在于内存的堆上,而是独自保存在一个区域,因此,再执行多态行为时,java会动态的去匹配传入对象的方法...多态还有一个名字叫动态绑定,多态是编译期行为
个人认为这是Java中引用的概念和C++指针概念差别的一处体现
首先,Java里肯定会报ClassCastException,这个行为大家都理解,并且都认同,因为本来嘛,一个父类引用强制转为子类引用,编译器不会complain,但运行时会进行真正的类型转换,将父类转为子类,这当然是扯淡,类型检查时发现不兼容,报错。而C++呢,我个人认为,仅仅个人认为,他未尝不想像Java一样,在这种情况下报一个运行时错误,甚至一个compiler错误来警告这个傻X的程序员,但指针的语义没有允许他这么做,指针说到底是从C继承来的,必须保持和C中指针的语义一致,这个指针被转换为子类,但指向的对象仍然是父类,在这里C++指针和Java引用的区别产生了,C++指针不仅在编译时不会报错,在运行时也不会进行类型转换——个人认为这是C指针的遗产,C是一个weak type的语言,指针强转不会动态检查类型,C++为了包容C,指针在这一点上的行为并没有改变,所以这个父类对象开始进行函数名匹配,找到test,调用,当然,他从根本上就看不到Boy或者Girl的test函数,他只能匹配到自己的。所以,打出
Father
Father
Father而C++中也有引用,如果把楼主这个例子改成
Father f;
Boy &b=f;
Girl &g=f;
会怎么样呢?编译器压根就不让你过!由此,我们可以看到,C++中的指针,Java中的引用,C++中的引用虽然彼此都有相似的地方,但还是有很大区别的,就严格性和安全性而言,
C++引用>Java引用>C/C++指针这是我个人的理解,大家多指正。