看了那个贴子,也来谈谈C++和java的语言陷阱

sliant 2004-04-28 12:46:01
http://expert.csdn.net/Expert/topic/3013/3013478.xml?temp=.9383509
默认参数这一点我猜错了 运行后才想通
其实我觉得 java 的语法比起 C++ 来简单 是java的优点
这个贴子的题目其实是C++的缺点,是C++程序中应该避免的
甚至我觉得 java 的语法都应该更简单一点 里面也有很多陷阱
《effective java》里面就有很多 java语言规范简直就是java 语法陷阱大全
随便举几个例子:
1、 子类会覆盖父类的同名变量,如果子类可以访问这些变量的话;导致的结果是:尽量把所有的变量声明为private,而通过 get/set 方法让子类访问;否则用户继承一个类,然后不小心覆盖了变量,就会产生一些隐蔽的bug
2、 包级访问权限(就是缺省访问权限)的方法,子类不能访问却能改写(C++中也有类似的问题)。导致的结果是:所有的包级访问权限方法都应该声明为 final ,虽然明知别人无法访问
3、 函数参数的自动类型转换与提升也很容易出错。
比如,类A有两个同名函数 void f( Object ) 和 void f( String )
猜猜看,A.f( null ) 会调用那一个?
...全文
45 39 打赏 收藏 转发到动态 举报
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
Hmilu 2004-04-29
  • 打赏
  • 举报
回复
Learning
allenhe 2004-04-29
  • 打赏
  • 举报
回复
oyd(cpp<JavaIsNotPlatform_Independent>)(MVP)
你先要明白,java并不是不能做,而是不想做
你说的'多继承、运算符重载、默认参数、模板'
前三个已经否决,具体原因我想只要关心java.sun.com的不太可能不知道
并且java分别提出了更有效的解决方案,并且说明了为什么在将来也不会支持
第四个在此不想浪费口舌

我看到你不少贴子,我认为你在罗列自己论据的时候最好先设想一下,为什么java要这样,然后再告诉自己,java不是C++的效仿者,并不是C++能做什么,java就要实现什么。


至于 sliant() ( )的三个例子
1,3编译不通过
2瞎掰

我建议你多写写代码
programer23 2004-04-29
  • 打赏
  • 举报
回复
study
Wolf0403 2004-04-29
  • 打赏
  • 举报
回复
C++ 和 Java 其实就类似 Perl 和 Python。
一个灵活而方便,一个严谨而方便。具体感觉如何,个人都不同罢了。我喜欢 Java 的匿名类、interface、class Class,也喜欢 C++ 的模板 meta-programming、多继承、默认参数,无所谓。有什么好吵的?

相比之下,Java 比 C++ 更容易达到实用的程度。这是它的优点,也是缺点:容易让人们急功近利。sliant 最后这话却是有点过激了。
sliant 2004-04-29
  • 打赏
  • 举报
回复
无语。
我在C++论坛和java论坛都呆过,以下这些话是我的个人体会。
越新潮的东西,比如java,从事的人就越多,而且没礼貌
老旧的,难学的,比如C++,大家还能静下心来讨论问题

如果编译不通过的话,很可能你根本就没理解问题。
紫黑蓝白 2004-04-29
  • 打赏
  • 举报
回复
支持:
----------------------------------------------------------------------
allenhe(勤劳的民工)

oyd(cpp<JavaIsNotPlatform_Independent>)(MVP)
你先要明白,java并不是不能做,而是不想做
你说的'多继承、运算符重载、默认参数、模板'
前三个已经否决,具体原因我想只要关心java.sun.com的不太可能不知道
并且java分别提出了更有效的解决方案,并且说明了为什么在将来也不会支持
第四个在此不想浪费口舌

我看到你不少贴子,我认为你在罗列自己论据的时候最好先设想一下,为什么java要这样,然后再告诉自己,java不是C++的效仿者,并不是C++能做什么,java就要实现什么。


至于 sliant() ( )的三个例子
1,3编译不通过
2瞎掰

我建议你多写写代码
------------------------------------------------------------

赞同!
sliant 2004-04-29
  • 打赏
  • 举报
回复
allenhe(勤劳的民工)
虽然我是java的拥护者,但我觉得你否决java和C++的关系太武断了
一般大家是认为 C/C++/java 是一系的语言,java也是有意模仿 c/c++ 语法的,unix的一位创始人(名字我忘了,d打头的那一位)发表过这个言论,在网上很容易搜到(他建议学习
4种语言,其中讲到了这一点)

另外我举的例子都是可以编译通过的,第2个我理解有误(忘记放到不同的包中去了),但是代码是我亲手编译通过的
sliant 2004-04-28
  • 打赏
  • 举报
回复
再次声明,第二个是我错了 :-( 包外不能见,所以就不能重载,只能是完全新添一个方法,在 eclipse 中会给警告。而在包内的重载就是普通的重载,就是我举的那个例子。

我倒是觉得,基本上所有 java 比 C++ 简化的地方,都是经过了深思熟虑的,比如默认参数, C++ 中这么做:
void f( int i=99 ) {...}
但是用同名函数完全可以解决这个问题,java 中都是使用两个函数
void f( int i ) {...}
void f() { f(99); }
这样一样实现了默认参数,虽然麻烦了一点点,但是一目了然,不容易出错。特别是有多个默认参数的时候, C++ 那样很容易出错的。
oyd 2004-04-28
  • 打赏
  • 举报
回复
默认参数也许是一个有争议的特性。
但是他的恰当使用会给用户带来好处,前提是默认参数的制定者应该保证对大多数用户该参数是合适的,否则就不要使用默认参数。

我举一个例子:假如我去店里吃面,厨师开始不停的问我:面要粗的还是细的还是韭叶的?
要不要放香菜?要不要放辣椒?要不要放榨菜?要不要肉丝?......
你们说我会不会抽他?我有特殊要求我自然会提,他那么多废话,到底还让不让人吃面呀?
bsking 2004-04-28
  • 打赏
  • 举报
回复

哇~~~~~~~~~~~~~~~~~~~~~~~~~~~

受益颇丰!!

受益颇丰!!
oyd 2004-04-28
  • 打赏
  • 举报
回复
变量在C++中其实可以是多态的,这一点java没有提供足够的灵活性

java 的语法比起 C++ 来简单 是java的优点
------------------------------------------
这一点我不认同,如果简化没有带来灵活性,反而是限制了程序员的发挥,这不能算是优点。
如果说RISC的精简指令集比CISC的复杂指令集有优点,这倒是真的。
而java的语法比起C++来,没有做到精简,只算是减少。
bluesmile979 2004-04-28
  • 打赏
  • 举报
回复
2、 包级访问权限(就是缺省访问权限)的方法,子类不能访问却能改写(C++中也有类似的问题)。导致的结果是:所有的包级访问权限方法都应该声明为 final ,虽然明知别人无法访问


这个具体是什么地方提到的?原文应该只是说因为种种原因除非你有意设定用来继承的方法,其他都要尽量设计为final的。

包级访问权限(就是缺省访问权限)的方法,子类不能访问却能改写。这个我没有测试,不过。。。原文真的是这么说的么?不应该啊。包外应该继承都有问题,何来包外的子类一说?
haha1903 2004-04-28
  • 打赏
  • 举报
回复
丢死人了,我回去试了一下,这次居然和你说得一样的,但为了学习,不要脸皮了。多谢楼主的教诲,我会记住的。
haha1903 2004-04-28
  • 打赏
  • 举报
回复
谢谢 sliant ,是我对 override 理解得不好,我没注意到变量是不能 override 的。

小弟才疏学浅,刚才言语之间的冒犯,请见谅。

第 2 个例子我会好好看看。

第 3 个我就十分不解了,在我这里,如果同时定义
f(String),f(File),f(Object)
然后调用的时候用 f(null) 会在编译期出错,而不会像你说的匹配最深的那个子类,为什么呢?
sliant 2004-04-28
  • 打赏
  • 举报
回复
第2点有误,只有在同一个包中才能改写,不能访问的话是不会改写的
sliant 2004-04-28
  • 打赏
  • 举报
回复
1、 “覆盖(override)”这个说法可能比较含糊。我说的是,父类变量(private除外)会被子类的同名变量隐藏起来。变量不象方法,没有多态这个概念。变量就是存放在对象的地址空间中的(static除外),所以任何变量是引用的究竟是父类还是子类的同名变量,是在编译期决定的。haha1903(中国人) 的例子中,Test2的对象内存中有两个变量i, 但是具体代码中的i指的是那一个,在编译期就定下来了, java语言规范中讲得很详细。

2、 可能我说的不清楚,haha1903(中国人)看看这个例子就知道了。其根本原因是,除了 private 外, package、protect、public的方法都是多态的、运行期才确定的,所以不能访问的方法也有可能被改写(override或者说重载)
class A {
void f() { g(); }
void g() { System.out.println( "A" ); }
}

class B extends A {
void g() { System.out.println( "B" ); }
}

public class Main {
public static void main( String[] args ) throws Exception {
A a = new B();
a.f();
}
}

3、 方法的参数在匹配时,是匹配继承最深的子类的那一个。因为 String 是 Object 的子类,而 null 什么都能匹配,所以 f( null ) 会匹配 f( String ) 。f( File ) 会匹配 f( Object ) 。 如果一个都不能匹配,就会编译出错。
Aa7643 2004-04-28
  • 打赏
  • 举报
回复
很同意Arias(道)的说法!
sliant 2004-04-28
  • 打赏
  • 举报
回复
oyd(cpp<JavaIsNotPlatform_Independent>)(MVP)
你不用这些特性,并不代表你的程序就低人一等了。这种思想导致一些一知半解的程序员,在分明没必要的情况下,去封装了几个对象,强加上继承关系,然后看着还不爽,就给加上模板参数和几个虚基类,最好放到一个名字空间中。好像不这样写程序就会很丢脸一样,而这样的结果呢,发现程序非常糟糕,于是他们开始诟病C++的不是。
------------------------------------------------------------
说得很好!深有体会。就算在 java 中,也应该这样。比如,不考虑多线程的就不要额外考虑 volitile ,不考虑 serialize 的就不要使用 transient 。写小型的程序, private,package,protect和public都不需要全部用上,只使用 package 和 public ,程序会显得更清晰。写程序的时候,特别是小型程序,应该针对性的选择语言特性的一个子集供自己使用就好
feiyuwen 2004-04-28
  • 打赏
  • 举报
回复
这个void f( String )
yunuo2010000 2004-04-28
  • 打赏
  • 举报
回复
学习
加载更多回复(19)

62,614

社区成员

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

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