热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C++本质的缺陷,欢迎来探讨!

一直从事C编程工作,以前学过C++,但是对STL不是很精通,今天翻了下C++PRIMER讲STL部分,个人认为C++有以下缺陷,欢迎大家研讨和斧正。1所有对象不是从一个基类派生的。

一直从事C编程工作,以前学过C++,但是对STL不是很精通,今天翻了下C++ PRIMER讲STL部分,个人认为C++有以下缺陷,欢迎大家研讨和斧正。

1 所有对象不是从一个基类派生的。
  
  C++,应该有一个超类,是所有类的基类 提供所有对象的基本方法,类似于JAVA中Object类。


2 STL中的算法和数据分离。

  我认为面向对象相对面向过程的思想更贴近人的思维,可以构建现实世界模型的映射,使得面向对象编写的代码,便于管理和维护。类把数据和行为(算法)溶为一体,使得编程语言活泼生动反映客观世界。
  而在STL的模型,是把数据结构,算法,和迭代器区分使用的,个人认为不符合面向对象的思维。
比如针对每种容器都有自己的算法,当然这些类都可以继承这些算法的类(或者说接口)。

比如一个Vector类自己有一个sort排序方法,Vector继承了抽象类的Sort类的Sort方法

Vector v;
.....

v.sort();

个人这样好些,希望大家讨论

58 个解决方案

#1


1==>用JAVA吧。
2==>泛型编程。

#2


1,类似CObject呵呵.这可不是好事,很容易出现菱形之类的继承的。除非你的类都用单继承.

#3


我觉得这两个都算不上“缺陷”,顶多是两个值得讨论的话题。
面向对象是不是万能的?类是不是该有单根体系?这些以前已经有过很多争论。
至于说孤立函数对于成员函数的优势,“Exceptional C++”三卷本中有相关的论述,当然也不见得完全正确,因为这里本来就没啥正不正确的,不过值得参考。

#4


典型的井底之蛙……

.net/java 的类组织形式的确适合快速开发,尤其是语言的快速掌握。但 OOP 体质是有着先天缺陷的,你这个题目取反了,应该说是对比 C++ 你应该发现 .net/java 的先天缺陷才对。

OOP 体质是什么先天缺陷呢?看我的博文吧,在 C# 和 F# 里面有着比较详细的讨论,JAVA 的情况只能更糟。

你这两点其实都是站在 OOP 的视角上来看的,严格的 OOP 体系才有 object 基类和算法和数据结构封闭在类体内的情况出现。

或者你认为你可以通过 JAVA 写出我在 

http://blog.csdn.net/hikaliv/archive/2009/09/16/4559927.aspx

文中所举的更优的例子。

或者你认为 OOP 可以写出如我在

http://blog.csdn.net/hikaliv/archive/2009/08/10/4431824.aspx

中所举的算法,不要求你写得比之高效,你能写出来就行。

至少能让你明白,到底谁才有缺陷。

#5



汗! 感觉说的全是C++优势所在。

#6


引用 4 楼 hikaliv 的回复:
典型的井底之蛙……

.net/java 的类组织形式的确适合快速开发,尤其是语言的快速掌握。但 OOP 体质是有着先天缺陷的,你这个题目取反了,应该说是对比 C++ 你应该发现 .net/java 的先天缺陷才对。

OOP 体质是什么先天缺陷呢?看我的博文吧,在 C# 和 F# 里面有着比较详细的讨论,JAVA 的情况只能更糟。

你这两点其实都是站在 OOP 的视角上来看的,严格的 OOP 体系才有 object 基类和算法和数据结构封闭在类体内的情况出现。

或者你认为你可以通过 JAVA 写出我在

http://blog.csdn.net/hikaliv/archive/2009/09/16/4559927.aspx

文中所举的更优的例子。

或者你认为 OOP 可以写出如我在

http://blog.csdn.net/hikaliv/archive/2009/08/10/4431824.aspx

中所举的算法,不要求你写得比之高效,你能写出来就行。

至少能让你明白,到底谁才有缺陷。


 谢谢你让我看了你的博文,我简要的看了你的博文,
“当看到一只鸟走起来像鸭子,游起泳来像鸭子,叫起来也像鸭子,那这只鸟就可以被当做鸭子。”
这个是比喻在类的设计中使用继承不恰当的例子。
而在程序开发中,存在所有类中都有一些共同的东西。
比如类似JAVA toString方法,可以把类的名字打印出出来便于调试。

看了第二篇文章总感觉编译不过去,“  这段代码现在在 VS 2010 上已无法打印所有的质数,而只会打印离 LAST 最近的那个质数,这里是 7,到此便停止向深层递归,不知这算不算编译器学聪明了……若有哪位读者有其它的编译器可以做自我验证。”
我拿VS 2010 Beta版本测试下,真的编译不过去。。
”error C2440: 'initializing' : cannot convert from 'int' to 'LB'“

#7


语言都有自己的优势,放弃优势,向别的语言靠拢,必要性不是很大吧...

#8


C++没有所谓的超类,是为了兼容c的一些特点,保持高效率。而且可能会存在不同的类,他们不具有共同的祖先,没必要有一个共同的超类。

第二个恰恰是为了实现面向对象的同时保持对类的具体类型不知情,实现隔离性,这也是泛型设计的目的。

#9


存在即合理~

#10


超类?为什么一定要有个超类呢
这个不管总哪方面讲都不能算是个缺陷

#11


Quote=引用 4 楼 hikaliv 的回复:]
典型的井底之蛙……

.net/java 的类组织形式的确适合快速开发,尤其是语言的快速掌握。但 OOP 体质是有着先天缺陷的,你这个题目取反了,应该说是对比 C++ 你应该发现 .net/java 的先天缺陷才对。

OOP 体质是什么先天缺陷呢?看我的博文吧,在 C# 和 F# 里面有着比较详细的讨论,JAVA 的情况只能更糟。

你这两点其实都是站在 OOP 的视角上来看的,严格的 OOP 体系才有 object 基类和算法和数据结构封闭在类体内的情况出现。

或者你认为你可以通过 JAVA 写出我在

http://blog.csdn.net/hikaliv/archive/2009/09/16/4559927.aspx

文中所举的更优的例子。

或者你认为 OOP 可以写出如我在

http://blog.csdn.net/hikaliv/archive/2009/08/10/4431824.aspx

中所举的算法,不要求你写得比之高效,你能写出来就行。

至少能让你明白,到底谁才有缺陷。
[/Quote]


好了,我编写你要我编写的JAVA代码,我写了,没有出现Person是Duck的笑话,请严谨点,当你仔细研究好面向对象后,再来发言好不。
而且使用Object很合适!


class Person{
public void Qucak(){
System.out.println("A persion Quack");
}
}
class Duck{
public void Qucak(){
System.out.println("A Duck Quack");
}
}
public class Test {

public static void CheckAsDuck(Object c){
if(c.getClass() == Duck.class){
((Duck) c).Qucak();
}
else{
System.out.println("This is not a Duck");
}
}
public static void main(String[] args) {

Person person = new Person();
Duck   duck   = new Duck();
CheckAsDuck(person);
}

}


输出的是This is not a Duck

#12


上边JAVA,C#能实现,而C++好像在VC MFC提供这种机制,标准C++好像没有,除非自己写一个吧。

#13


1.  如果全部使用同一个基类,则在程序中就会出现大量的基类使用。那麽程序将大部份时间用来分辨衍生类。那麽C++变成Java那麽的低效,那不如直接用Java吧。

2. 容器与算法分离的优点,正正就是保持其抽象,使容器与算法拥有各自的发展方向,C++标准认为string就是一个容器与算法捆绑在一起的失败之作。

楼主可能对C++认识未深,看到的是C++的表象,不知道C++背後为工程人员的一片苦心。

#14


真正意义上的C++仅仅只是提供了一个非常严谨、灵活的语言核心而已。而你说的那些全都被称为库,或是框架。
在不同平台下都有其各自的框架。比如,一个不怎么样的MFC框架就有CObject,对应于Java的Object。
而一个非常优秀的Coco Framework则定义了Object作为所有类的超类,并且也对应于Java的Object。

STL库主要是用于泛型。而你用Java所举的例子其实是比较糟糕的。你使用了反射,这对于运行时的存储器占用而言非常高。
而C++大多用于系统或嵌入式应用开发,对运行时性能以及存储空间的要求相对较高。
楼主也可以用C#开发的Vista和用C++开发的Win7进行对比一下,结果是显而易见的。

#15


11 楼,你使用了 反射。这正是我在文章中批判的。

既然你觉得你懂 OOP,那么应该会有这样的认识:

当你用基类来推导派生类时,你并不知道派生类的情况。你无法预知派生类是什么情况,所以你有两种方法来解决这个问题:一个是机制上的,反射;一个是算法上的,你要遍历所有可能的情况。而反射本质上也是一种遍历。你觉得你的代码“很简单”,而背后隐藏着多么复杂而臃肿的过程,表现上是看不出来的。EFFECTIVE 系列对这类问题有过很多的讨论。不管是 EFECTIVE C# 还是 JAVA。

还有,反射是运行时的,C++ 和 F# 强调编译时,比如C++模板和F#内联泛型。你能用 OOP 语言写出模板或者内联泛型么?你是写不出来的。放心吧。而 C++ 和 F# 可以做到,而且运行时泛型也可以写,只不过认为这不值得而不愿意去实际操作罢了。

你写出了东西,但却没有跳出思想。你的有点那什么的留言,我删除了,鉴于你的那些回复,我不想说什么,劝你,该删除的是应该是你的固化思维。

#16


或者你好像并没有看懂我在文章中肯定什么,批判什么。你的代码和回复印证了我的批判。

#17


围观

#18


每个语言都有自己的定位,
在一种语言中是优点的特性,跑到定位不同的语言里,可能就是缺陷,
TIOBE统计数据表明,Java>C>Php>C++,并没有出现哪种语言一边倒的迹象。

#19


我是专程来学习的。up

#20


可以肯定,楼主看过的书很少。至少没有完整的看完一本书。

#21


我是来打酱油的。。。

#22


裘宗燕翻译《C++程序设计语言》
第386页的容器设计。讨论了这个问题。

第二个问题就是大家认为其优秀的原因。你却把它看做是缺点!

#23


引用 11 楼 haohaokingxp 的回复:
Quote=引用 4 楼 hikaliv 的回复:]
 典型的井底之蛙……
 好了,我编写你要我编写的JAVA代码,我写了,没有出现Person是Duck的笑话,请严谨点,当你仔细研究好面向对象后,再来发言好不。
 而且使用Object很合适!

Java codeclass Person{publicvoid Qucak(){
        System.out.println("A persion Quack");
    }
}class Duck{publicvoid Qucak(){
        System.out.println("A Duck Quack");
    }
}publicclass Test {publicstaticvoid CheckAsDuck(Object c){if(c.getClass()== Duck.class){
            ((Duck) c).Qucak();
        }else{
            System.out.println("This is not a Duck");
        }
    }publicstaticvoid main(String[] args) {
        
        Person person=new Person();
        Duck   duck=new Duck();
        CheckAsDuck(person);
    }

}

 输出的是This is not a Duck


person Qucak 本来就是个笑话。。

#24


俺是来学习的

#25


还没学C++的人飘过~~~

#26



内联函数只是宏,宏的级别早在C中就已经实现了,
你举得例子不能算是OOP本质缺陷,只能算是使用OO思想设计时候容易产生的缺陷。

无论是JAVA,C#编译器都有能力实现这种宏级别的检查机制,编译器其实能做到这些,为什么没有加入呢。
你举得那个F#例子,说明在编译前函数地址已经是确定的。

而JAVA 思想本质是强调在狂平台特性,在运行前函数是不知道确切地址的!
而C#思想也是如此,尽管只是在windows跨平台。

而C++在使用多肽的时候,父类指针指向派生类的时候,调用派上类函数的时候,地址也是无法确定的,也是在运行时候确定的。

#27


存在即合理~

#28


MFC 有CObject

#29


先看看《C++语言的设计和演化》

#30


泛型方法。我很喜欢

#31


一句话,不要为了面向对象而面向对象。
面向对象不是万能的。

举个简单例子,你能用面向对象进行图像编程?这涉及到大量线性代数,概率之类的数学计算。

如果你真能这么搞,恭喜你,数学不用再搞抽象了,数学不用再号称对象无关了,你可以把面向对象的概念引入数学了。

STL之类的就是数据结构算法之类的,你真要坚持,用彻底的面向对象搞个STL吧,Java面向对象比较彻底些,或者你可以用Java搞个STL库,或者用Java搞图像编程,随你怎么搞罗~

#32


   特别讨厌那种就知道在网上说这种语言不行,那种语言不好的人。俗话说:“金无足赤,人无完人。”
更何况是一门由人设计出来的语言,能没有缺陷吗?也不想一想如果没有缺陷那它还能叫做C++吗?也不
想一想,要不是C++有这些所谓的缺陷,那各位以为它还会有这么多的激情吗?

#33


楼主,面向对象又不是一切,你看看人家的blog吧。

泛型,ducking type,functional prog都很精彩啊。

#34


楼主既然已经对java、C#什么的这么了解,又何必再搅C++浑水。
你既然要学门新的,不如考虑erlang、lisp、haskell。。。。

#35


1 所有对象不是从一个基类派生的。
 
  C++,应该有一个超类,是所有类的基类 提供所有对象的基本方法,类似于JAVA中Object类。 
-----
C++的类是表示一个概念,并不一定要求用一个你说的超类来把这些概念联系到一起。好比C里面的整数,包括char, short, long, int,你觉得C有没有必要在定义一个种“整数”类型来表示所有的这些整数类型呢?


2 类把数据和行为(算法)溶为一体,使得编程语言活泼生动反映客观世界。而在STL的模型,是把数据结构,算法,和迭代器区分使用的,个人认为不符合面向对象的思维。 
-----
为啥一定要用面向对象去理解STL呢?再说那些搞JAVA的不是也提倡MVC,将数据,控制,视图分离吗?只是你把类看成了组成世界的一切。不过范型貌似在概念上更加道法自然,只是编成语言并没有过多地展现而已。
范型的算法就是,不管你是什么类,不管你具有什么样的基类,只要你具备这个算法的要求,那你就可以使用这个算法。不过这两点面向对象和范型并不冲突,只是看你从哪个角度去理解这个世界罢了。

LZ不接受和不理解C++的思维方式,只是没看透背后的道理。

#36


不能说是缺陷,应该说C++的特色。

#37


显然面向过程更符合人类思维,书本上那些什么汽车飞机的例子根本就不是真正的面向对象,纯粹是用来骗你入门的,面向对象里三大特征:封装、继承、多态,这些例子仅仅体现前两个,只能算高级的基于对象或阉割的面向对象,多台才是面向对象最本质的特征,而一旦有多态,一旦有抽象类,一旦有设计模式了,面向对象就不是正常的人类思维了,仅仅是为了维护方便。

#38


路过......

#39


学习哦

#40


人的通常思维是顺序的,而不是跳跃和继承的,尤其对于我们这些工匠思维的工科人员,面向对象也许更符合艺术家的思维,但是对于程序人员来说,没学过面向对象的很难理解面向对象的那种封装、那种抽象的“为什么”(说过了,不要用汽车飞机交通工具的例子,那不是面向对象),而熟练地面向对象设计人员,安全是根据经验和设计模式理论在设计,他对于面向对象的理解是建立在已有的知识基础上,而非人类的自然思维

#41


大家可以去看看设计模式的书就能理解我所说的,通常设计模式不会涉及到具体的语言,不需要编程的基础,但是,不会编程乃至于会编程但经验不足的人,看设计模式基本看不懂,为什么这些“符合人类思维习惯的面向对象设计模式”你没有知识和经验基础却看不懂,唯一的解释就是“它实际上不是人类的正常思维方式”,而仅仅是一种适合于软件开发、降低维护成本的的方式。

#42


哎。。。。

#43


引用楼主 haohaokingxp 的回复:
2 STL中的算法和数据分离。 

   我认为面向对象相对面向过程的思想更贴近人的思维,可以构建现实世界模型的映射,使得面向对象编写的代码,便于管理和维护。类把数据和行为(算法)溶为一体,使得编程语言活泼生动反映客观世界。

但并不需要把“所有”的算法都融到类里面,好比用JAVA,你的一个程序会制定很多类,始终有类外的方法去关联它们。
回到STL的sort函数。一个单独的函数并不能仅仅因为编码的形式就用面向过程的角度去看待。面向过程的函数仅仅接纳一种struct对象,但STL并不是,它接纳所有的迭代器,例如copy,他要求一个OutputIterator,你可以传一个容器的iterator,也可以把容器弄成iterator adapter,让它看起来像一个迭代器。这样就和类型没有任何关联,唯一关联的是这个类是否具备范型的概念要求。既然迭代器可以从容器中分离出来,让外部通过迭代器访问元素,只需要实现一个通用的算法作用于所有的容器,那为何还需要单独为每个容器实现相同的算法呢?回到面向对象上,既然一个方法能接纳一个base类,任何子类都可以用这个方法,那也就不需要为每个子类都去实现这个同样的方法。

#44


1 java不是也有原生类型吗? long boolen啥的
2 面向对象不是万能的,对象和对象之间的关系,不一定很密切,不要指望所有的对象都成为一个继承体系。
难道还指望int 和float这些原生类型都有继承关系?

Please note that object-oriented programming is not a panacea. "OOP" does not simply mean "good" - if there are no inherent hierarchical relationships among the fundamental concepts in your problem then no amount of hierarchy and virtual functions will improve your code. The strength of OOP is that there are many problems that can be usefully expressed using class hierarchies - the main weakness of OOP is that too many people try to force too many problems into a hierarchical mould. Not every program should be object-oriented. As alternatives, consider plain classes, generic programming, and free-standing functions (as in math, C, and Fortran).

Generic programming is in some ways more flexible than object-oriented programming. In particular, it does not depend on hierarchies. For example, there is no hierarchical relationship between an int and a string. Generic programming is generally more structured than OOP; in fact, a common term used to describe generic programming is "parametric polymorphism", with "ad hoc polymorphism" being the corresponding term for object-oriented programming. In the context of C++, generic programming resolves all names at compile time; it does not involve dynamic (run-time) dispatch. This has led generic programming to become dominant in areas where run-time performance is important.

Please note that generic programming is not a panacea. There are many parts of a program that need no parameterization and many examples where run-time dispatch (OOP) is needed. 

http://topic.csdn.net/u/20091118/22/c30c52e4-2ee1-43f5-9fe2-913908029d8b.html?58983

#45


垃圾回收始终是c++的痛。。

#46


http://www2.research.att.com/~bs/bs_faq.html#oop

#47


建议所有论坛中c++ers都到这看一下
Bjarne Stroustrup's FAQ
http://www2.research.att.com/~bs/bs_faq.html#oop

#48


有时候,某些事物的优点在一些人的眼里反而容易成了确定啊
凡事有利必有弊

#49


引用 45 楼 forster 的回复:
垃圾回收始终是c++的痛。。

无法改变,内存安全语言的效率问题的根源其实就是自动内存管理(C#在运行时会编译为本机代码,虚拟机体制只影响启动速度,而运行速度不会因.net的存在而大多打折扣),C++的应用方向决定了不可能内存安全,只能用内存池等方式简化管理

#50


jf

推荐阅读
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
author-avatar
永恒多一天_313
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有