我在这里某个问题的答案之一(不记得是哪个)中读到C ++不适合面向对象的编程。有人提到您可以利用它的功能或类似功能,但不能纯粹从面向对象的角度来理解(我实际上并不真正了解此人的意思)。
这有什么道理吗?如果是这样,为什么?
我在这里某个问题的答案之一(不记得是哪个)中读到C ++不适合面向对象的编程。有人提到您可以利用它的功能或类似功能,但不能纯粹从面向对象的角度来理解(我实际上并不真正了解此人的意思)。
这有什么道理吗?如果是这样,为什么?
Answers:
正如Alan Kay所描述的,“面向对象”一词到底是什么意思?,Alan Kay认为消息传递是OOP的重要部分,但是缺少“带有类的C”(后来变成C ++)。C ++只是具有一些行为的结构,而Smalltalk或Objective-C中的对象是“智能的”,因为它们可以决定如何处理发送的消息。如果类似Smalltalk的对象收到没有实现的消息,则可以延迟添加一条消息,将该消息转发到另一个对象,或执行任意操作。
C ++以面向对象的方式提供的是virtual
方法和涉及这些方法调用方式的多态性。当编译器看到class
具有虚拟方法的数据类型(或)时,它会为每个虚拟方法构造一个带有槽的vtable。实现虚拟方法的子类会将其实现放在正确的位置,因此客户端代码只需要知道虚拟表中的位置来查找要运行的代码,而不是一直将其解析为特定的功能。这意味着C ++实际上确实具有多种分派的形式,尽管它们都是在编译器中实现的,并且不如Smalltalk式系统那样强大。
如果您将消息传递作为OOP的基础,那么尽管可以使用C ++ 进行传递,但要实现这一目标并非易事。OTOH如果您认为OOP意味着将数据与作用于该数据的函数相关联,则C ++很好。
C ++借鉴了Simula的OOP功能。一个或多个Simula开发人员IIRC认为C ++不是他们的初衷。
C ++有很好的抽象工具,但它是一种混合范例语言,而不是面向对象的语言。那里有面向对象的功能,但是您可以选择的不是“严格的OOP”。
在C ++中,调皮的“选择退出”之一是对方法使用早期绑定而不是后期绑定。这不仅可能-这是默认设置。在Java中,“最终”是相关的,但在某些方面更清晰(它以不仅仅避免微不足道的性能开销的方式指定了意图),而且它不是默认值。
在某些方面,C ++显示出仍在进行早期实验的迹象。即使这样,它仍然是一个很好的工具,它具有许多其他OOP语言所没有的优势。
强迫所有内容成为类的一部分并不一定会产生出色的OO代码。
要求一个程序差的程序员用Java编程,他们可能会在某个地方带一个类,给它一个静态的main方法,并在其中粘贴1000行代码。我知道我已经看过。
Java有一个switch语句。我已经switch( type ) { case typeA: bundles_of_code; break; case typeB: bundles_of_other_code; break }
在C ++和Java代码中看到了等等。
C ++支持许多OO概念,但是它没有定义其标准,但是我想很大程度上取决于您的目标是什么。
C ++中主要的“较差”语义是允许类的复制构造,从而使一个对象变形为另一个对象。您可以禁用此功能,但是不能从函数中返回一个。幸运的是,这在C ++ 0x中已解决。
尽管我不同意这种观点,但是C ++的类型系统确实不是纯OOP,这不是“一切都是对象”。数字(尤其是数字)不能像在Smalltalk中那样容易地扩展。例如,您不能重新定义“ 2 + 2”的含义(尽管您可以重新定义“两个+两个”的含义)。
但是大多数人可能意味着许多人使用C ++编写非面向对象的代码,但他们相信,因为他们使用的是“ OOP”语言,所以它们是面向对象的。这不是真的。但是我认为,您可以在Smalltalk中编写可怕的命令性代码,而不比C ++中的体面OOP设计有任何优势。
艾伦·凯(Alan Kay)对C ++的完全正确的反对意见是,它是C语言之上的宏语言。
“消息传递”的概念仅仅是将类的实例保存在内存中,并且它们公开了可以调用的方法。在C ++中,使用持有函数指针的vtables“模拟了消息传递”。
要说消息传递在C ++中不存在是不准确的,更准确地说是消息传递是诸如Smalltalk和Java之类的其他语言的组成部分,因为该语言没有预处理外来结构并将其直接移植到C上。
这是一个高度语义化的语言设计论据,我怀疑这超出了发问者的经验水平。
话虽这么说,讨厌C ++的理由有千种,而讨厌C ++的理由却很少。
与其寻找完美的锤子和完美的钉子,不如寻找要建造的完美房屋,然后找到需要经验的正确工具。
同样重要的是要记住,在系统编程中,Alan Kay担心的不是“纯OOP”实际上是C ++的优势。对于每个人自己的...
在我看来,与其说是定义性问题,不如说是可用性问题。
对象是一种抽象,旨在使复杂程序的读取,编写和推理更加容易。对于实际的程序员而言,一种语言是否符合“面向对象”的特定正式定义的所有条件(似乎有几个相互竞争的条件!)并不像它所提供的工具是否适合思考那样重要。就上述对象而言,您的程序-即实际上获得了OOP所谓的生产率收益。
在C ++中,对象是一个非常漏水的抽象,经常迫使程序员解决与这些对象在内存中的结构有关的棘手问题,这些问题比起其他OOP语言更让人联想到直接C语言中的编码。例如,C ++常见问题解答提供了以下批评(以及其他批评):
对于从业人员来说,熟悉除C ++以外的OO系统以及除以特殊方式解释的“封装,继承,多态”三位一体以外的OO定义(使C ++被视为“ OO”)非常有益。例如,声称缺乏边界检查或垃圾收集的环境不是OO环境的说法对于习惯于C ++的人们来说听起来太离谱了。但是从许多角度来看,这很有道理。如果任何人都可以覆盖对象,那么“封装”在哪里?如果处理对象可能导致引用悬挂或内存泄漏,那么系统如何“面向对象” ?分辨给定地点和时间放置哪种物体的能力怎么样?您说该软件可与对象一起使用-它们在哪里?如果找不到,应该如何调试该软件?
C ++是面向对象的,但令人不愉快且不完整:它的用户必须付出很多努力才能确保其数据的行为实际上像“真实”对象,而不是错误的位。就是说,在C ++的整个生命周期中,已经编写了许多代码,其中大多数都是使用类和动态调度的,因此,不言而喻,您可以将其用于实际的OOP。
格雷厄姆·李(Graham Lee)在这里投票最多是有原因的。重申一下,就其不执行消息传递的意义而言,C ++类似乎并不是真正的对象。我认为这是使人们在学习C ++或oop时会感到非常沮丧的原因。人们被告知面向对象是“ this”,然后被告知C ++会以不同的方式进行操作。好吧,C ++从来没有做过OOP不同的事情。如果您以这种方式思考,您将永远不会理解C ++类的含义,那就是它们只是通过合并抽象和动态行为而对过程范式进行了改进。因此,C ++类在根本上是过程性的,它们只是在过程范式上得到了改进,或者说,它们是C结构的更高级版本。
史蒂夫·耶格(Steve Yegge)说得最好:
从最真实的意义上讲,C ++是地球上最愚蠢的语言。它不了解自己。
C ++中的对象系统是如此硬连线,并且在编译时已固定,以至于它与原始的OOP概念相去甚远,后者涉及消息传递,自省,反射,动态分派和后期绑定等。C ++和Smalltalk唯一的共同点是词汇量。