有关OO多态,C++高手且JAVA高手请进

whut_lcy 2010-04-22 04:19:43
与同事切磋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++同时都是高手的高手来解答一下:
为什么会有这种区别?
...全文
286 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
tomsheep 2010-04-27
  • 打赏
  • 举报
回复
我对楼主的这个问题非常感兴趣
个人认为这是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++指针

这是我个人的理解,大家多指正。
紫蕤 2010-04-26
  • 打赏
  • 举报
回复
上面写错了...多态是执行期行为...
紫蕤 2010-04-26
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 iefus 的回复:]

引用 21 楼 cclsoft 的回复:
Father f = new Father();
Boy b = (Boy)f;
Girl g = (Girl)f;
不能这样转换的 自能讲父类转为子类 例如:
f = (Father)b;
java 与 C++;一样


这个才是多态。
[/Quote]

这个只是强制转换...不是多态...

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会动态的去匹配传入对象的方法...

多态还有一个名字叫动态绑定,多态是编译期行为
Aniao 2010-04-26
  • 打赏
  • 举报
回复
C++的不加virtual不会多态的,因为从内存结构上来讲,如果不把函数写到虚表里无法实现多态

而JAVA的默认就是virtual的,加个abstract就是virtual =0
shore1111 2010-04-26
  • 打赏
  • 举报
回复
你是想问动态绑定吗
C++中满足动态绑定,第一必须是指针,第二必须是虚函数,应该这样写,前提是test为虚函数
Father *f = new Father;
Father *b = new Boy;
Father *g = new Girl;
f->test();
b->test();
g->test();这样应该就会打印出来了
如果按你说的话,应该都会打印father

java:
Father f = new Father();
Father b = new Boy();
Father g = new Girl();
fyhack 2010-04-25
  • 打赏
  • 举报
回复
父类对象是不能调用子类的方法,强制转换后,会丢失子类的非继承方法,
所以JAVA的应该全是Father吧;
C++的基类采用了指针对象,派生类的指针对象也指向了基类,这个输出我猜测是Father,Boy,Girl
SealedBook 2010-04-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 quxiaoyong 的回复:]
引用 6 楼 ying422 的回复:

JAVA的多态:

1.继承
2.父类引用指向子类对象
3.子类重写父类方法

Father f = new Father();
Boy b = (Boy)f;
Girl g = (Girl)f;

把你程序先修改一下再和你同事讨论多态...


第二条不懂
[/Quote]
Father f = new Boy();
父类引用f指向子类Boy
CreazyJava 2010-04-25
  • 打赏
  • 举报
回复

Father f1=null;
Father f2=null;
f1=new Boy();
f2=new Girl();
Boy b=null;
Girl g=null;
b=(Boy)f1;
g=(Girl)f2;
jackmtlee 2010-04-25
  • 打赏
  • 举报
回复
向下转换?编译都过不去。
CreazyJava 2010-04-25
  • 打赏
  • 举报
回复
向下转型的时候应该先向上转型吧~
suiyuefuchen 2010-04-25
  • 打赏
  • 举报
回复
向下转型是不允许的,因为会出现未知错误,也就是父类不可以转换为子类;但是如果超类是Object,子类是String,那么父类可以转换为子类;比如:Object obj = "sl"; String str = (String)obj;这个可以运行;向下转型编译可以通过,但运行时抛出ClassCastException异常;
humanity 2010-04-25
  • 打赏
  • 举报
回复
Java 中下面这个方法是相当于 C++ 的 virtual void test():
如果不希望 virtual 在 Java 中需要明确设定成 final void test() 才行。

void test() {

}

iefus 2010-04-25
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 cclsoft 的回复:]
Father f = new Father();
Boy b = (Boy)f;
Girl g = (Girl)f;
不能这样转换的 自能讲父类转为子类 例如:
f = (Father)b;
java 与 C++;一样
[/Quote]

这个才是多态。
qjtttt 2010-04-25
  • 打赏
  • 举报
回复
哦,我看反了-。-
qjtttt 2010-04-25
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 creazyjava 的回复:]
引用 18 楼 qjtttt 的回复:

引用 1 楼 believefym 的回复:
Father f = new Father();
Boy b = (Boy)f;
Girl g = (Girl)f;
-----------
能这样强制转换?

怎么不能了? 人家说有父类Father及两个子类Boy,Girl
Object可以强转为任何java类,莫名其妙


你可以……
[/Quote]
那ObjectOutputStream怎么用的请问?
cclsoft 2010-04-25
  • 打赏
  • 举报
回复
Father f = new Father();
Boy b = (Boy)f;
Girl g = (Girl)f;
不能这样转换的 自能讲父类转为子类 例如:
f = (Father)b;
java 与 C++;一样
CreazyJava 2010-04-25
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 qjtttt 的回复:]

引用 1 楼 believefym 的回复:
Father f = new Father();
Boy b = (Boy)f;
Girl g = (Girl)f;
-----------
能这样强制转换?

怎么不能了? 人家说有父类Father及两个子类Boy,Girl
Object可以强转为任何java类,莫名其妙
[/Quote]

你可以试试啊,可以通过编译,执行的时候就报错了
王二北 2010-04-25
  • 打赏
  • 举报
回复
Father f = new Father();
Father b = new Boy();
Father g = new Girl();
f.test() 结果为“father”;
b.test() 结果“boy”;
g.test() 结果“girl”;
qjtttt 2010-04-25
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 believefym 的回复:]
Father f = new Father();
Boy b = (Boy)f;
Girl g = (Girl)f;
-----------
能这样强制转换?
[/Quote]
怎么不能了? 人家说有父类Father及两个子类Boy,Girl
Object可以强转为任何java类,莫名其妙
eggno8 2010-04-24
  • 打赏
  • 举报
回复
学习了,顶
加载更多回复(11)

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧