当我用C / C ++进行编码时,我发现自己总是试图将所有内容都融入到OOP方法中。但我意识到,我并不总是强迫一切都进入这个模具。使用OOP方法有哪些优点/缺点?我对NOT使用OOP的优点/缺点更感兴趣(例如,不使用OOP有优化优势吗?)。谢谢,让我知道。
答案 0 :(得分:27)
当然,很容易解释为什么OOP是好事的百万个原因。这些包括:设计模式,抽象,封装,模块化,多态和继承。
何时不使用OOP:
面向对象的问题 语言是他们拥有这一切 他们携带的隐含环境 与他们在一起。你想要一个香蕉 但你得到的是一个大猩猩控股 香蕉和整个丛林。
向Emacs添加OOP显然不是 改进;我在工作时使用了OOP 在Lisp Machine窗口系统上, 我不同意通常的观点 这是一种优秀的编程方式。
您可以在本文中找到更多理由Bad Engineering Properties of Object-Oriented Languages。
Wikipedia's Object Oriented Programming page也讨论了一些优点和缺点。
答案 1 :(得分:7)
面向对象编程的一个思想流派是,您应该将所有在类上操作的函数作为类中的方法。
Scott Meyers,C ++大师之一,在本文中实际上反对反对:
How Non-Member Functions Improve Encapsulation
他基本上说,除非有一个真正令人信服的理由,否则你应该保持该课程的SEPARATE功能。否则,班级可能会变成这个庞大的无法控制的混乱局面。
根据之前大型项目的经验,我完全赞同他。
答案 2 :(得分:4)
非oop功能的一个好处是它通常可以更轻松地将您的功能导出到不同的语言。例如,一个只包含函数的简单DLL在C#中更容易使用,你可以使用P / Invoke来简单地调用C ++函数。因此,在这个意义上,它可以用于编写非常适合单个/少数函数调用的时间关键算法。
答案 3 :(得分:2)
嗯,有几种选择。 C ++中的非OOP代码可能是:
第一个的唯一优点是简单性和向后兼容性。如果你正在编写一个简单的小应用程序,那么搞乱课程只是浪费时间。如果您正在尝试编写“Hello World”,只需拨打printf
即可。不要打扰在课堂上包装它。如果您正在使用现有的C代码库,它可能不是面向对象的,并且试图将其强制转换为与其已经使用的不同的范例,这只是一种痛苦的处方。
对于后者,情况有所不同,因为这种方法通常优越到“传统OOP”。
通用编程为您提供更高的性能(除了其他因素,因为您经常避免vtable的开销,并且因为间接较少,编译器能够更好地内联),更好的类型安全性(因为确切的类型是已知的,而不是将它隐藏在接口后面,并且通常也是更简洁和更简洁的代码(STL迭代器和算法可以实现大部分功能,而不使用运行时多态或虚函数的单个实例。
OOP只不过是一个老化的流行语。每个人都误解的方法(C ++和Java支持的版本与OOP最初的含义几乎没有关系,如在SmallTalk中),然后假装是圣杯。当然,有些方面是有用的,但它通常不是设计应用程序的最佳方法。
相反,通过其他方式表达整体逻辑,例如泛型编程,当需要一个类来封装一些简单的概念时,一定要按照OOP原则设计它。
OOP只是许多人的工具。目标不是编写OOP代码,而是编写良好代码。有时,这样做的方法是使用OOP原则,但通常,您可以使用通用编程原则或函数式编程获得更好的代码。
答案 4 :(得分:2)
如果我们暂时考虑不是对象定位本身而是一个 面向对象的基石:封装。
可以证明,变化传播概率不会增加 与变化的距离:如果A取决于B而B取决于C, 然后我们改变C,然后改变A的概率 不能大于B的可预测性 更改。如果B是对C的直接依赖,则A是间接的 然后,更一般地说,依赖于C来最小化潜在成本 如果系统发生任何变化,我们必须最大限度地减少潜在的数量 直接依赖。
ISO将封装定义为信息的属性 包含在对象中的只能通过交互访问 对象支持的接口。
我们使用封装来最小化潜在依赖项的数量 具有最高的变化传播概率。基本上, 封装减轻了连锁反应。
因此,不使用封装的一个原因是系统是这样的 小的或不变的,潜在的涟漪效应的成本是 可以忽略不计。因此,这也是可能不使用OO的情况 没有潜在的代价高昂的后果。
答案 5 :(得分:2)
我建议你阅读Bjarne关于Why C++ is not just an Object-Oriented Programming Language
的论文答案 6 :(得分:2)
OOP在GUI代码,计算机游戏和模拟中经常使用。 Windows应该是多态的 - 您可以单击它们,调整它们的大小,等等。计算机游戏对象应该是多态的 - 它们可能有一个位置,一条可以跟随的路径,它们可能具有健康,并且它们可能具有一些AI行为。模拟对象也具有类似的行为,但会分解为类。
对于大多数事情来说,OOP有点浪费时间。状态通常只会造成麻烦,除非您已将其安全地放在它所属的数据库中。
答案 7 :(得分:1)
有了Ada背景,我根据包含数据及其相关功能的包在C中开发。这给出了一个代码非常模块化的代码,可以拆分并在其他项目中重用。我觉得不需要使用OOP。
当我在Objective-C中开发时,对象是数据和代码的自然容器。我仍然在开发时或多或少地考虑了一些新的酷炫功能。
答案 8 :(得分:1)
我曾经是一个OOP粉丝...然后使用函数,泛型和回调实现,通常可以在C ++中使用比类和虚函数更优雅和更改更友好的解决方案。
其他大牌也意识到了这一点:http://harmful.cat-v.org/software/OO_programming/
答案 9 :(得分:1)
这是一项非常依赖项目的决定。我对OOP的一般感觉是它对于组织涉及多个组件的大型项目很有用。我发现OOP特别无意义的一个领域是学校作业。除了专门用于教授OOP概念或大型软件设计概念的那些,我的许多作业,特别是那些更多算法类型的作业,最适合非OOP设计。
具体而言,较小的项目,不太可能增长,以及以单一算法为中心的项目似乎是我书中的非OOP候选者。此外,如果您可以将规范编写为一组线性步骤,例如,没有交互式GUI或要维护的状态,这也是一个机会。
当然,如果您需要使用OOP设计或OOP工具包,或者您在规范中有明确定义的“对象”,或者您需要多态性等功能等。等...有很多理由可以使用它,上面似乎是什么时候很容易就不会出现的指标。
只需我0.02美元。
答案 10 :(得分:0)
可能是一个不受欢迎的想法,但我认为你应该坚持使用非OOP,除非它增加了一些有用的东西。在大多数实际问题中,OOP很有用,但如果我只是在想一个想法,我会开始编写非目标代码,并将函数和数据放入类中,如果它变得有用的话。
当然我仍然在我的代码中使用其他对象(std :: vector等),我使用命名空间来帮助组织我的函数,但为什么要将代码放到对象中直到它有用?同样不要回避OO解决方案中的自由功能。
答案 11 :(得分:0)
在C语言中,有时候我会模仿面向对象的方法,通过在运行多个实例时定义某种类型的构造函数来控制回调等事情。
例如,假设我有一些漂亮的事件处理程序库,我知道在将来我需要许多已分配的副本:
所以我会(在C中)
MyEvent *ev1 = new_eventhandler();
set_event_callback_func(ev1, callback_one);
ev1->setfd(fd1);
MyEvent *ev2 = new_eventhandler();
set_event_callback_func(ev2, callback_two);
ev2->setfd(fd2);
destroy_eventhandler(ev1);
destroy_eventhandler(ev2);
显然,我稍后会做一些有用的事情,比如在两个相应的回调函数中处理收到的事件。我不会真正详细说明键入函数指针和结构来保存它们的方法,也不会在'构造函数'中继续进行,因为它非常明显。
我认为,这种方法适用于更高级的接口,它允许用户定义自己的回调(并在运行中更改它们),或者在处理复杂的非阻塞I / O服务时。
否则,我更喜欢更多的程序/功能方法。
答案 12 :(得分:0)
在C ++中你应该使用OOP。这是一个很好的抽象,它是你给出的工具。您可以使用它,也可以将它放在无法帮助的方框中。你没有使用电锯,但我会阅读手册并为正确的工作做好准备。
在C中,这是一个更难打的电话。虽然你当然可以在C语言中编写任意面向对象的代码,但是你很快就会发现自己正在使用该语言来使用它。你可能会更有效率地使用非常适合的设计模式和编程,因为C是打算使用的。
此外,每次在OOP-in-C设计模式中创建函数指针数组时,几乎都会完全切断继承链中的所有可见链接,从而使代码难以维护。在真正的OOP语言中,有一个明显的派生类链,通常会为您分析和记录。 (mmm,javadoc。)在OOP-in-C中不是这样,并且可用的工具将无法看到它。
所以,我总体上反对在C中反对OOP。对于一个非常复杂的程序,你可能需要抽象,然后你必须这样做,尽管需要在这个过程中对抗语言,尽管制作程序原作者以外的任何人都很难跟随。
但是如果你知道这个程序会变得那么复杂,你首先不应该用C语言编写它......
答案 13 :(得分:0)
我认为C ++ OOP的最大好处是继承和polymorphism(虚函数等......)。 这允许代码重用和可扩展性
答案 14 :(得分:0)
在我看来,它归结为什么样的模型适合手头的问题。在我看来,OOP最适合编写GUI程序,因为图形对象的数据和功能很容易捆绑在一起。其他问题 - (例如网络服务器,作为我头脑中的一个例子),可能更容易使用以数据为中心的方法建模,其中没有强大的优势使方法及其数据彼此接近。
tl; dr取决于问题。
答案 15 :(得分:0)
这个问题很棘手,因为OOP包含几个概念:对象封装,多态,继承等。很容易将这些想法推得太远。这是一个具体的例子:
当C ++第一次出现时,数以万计的字符串类本应运而生。你可以想象的所有对字符串做的事情(upcasing,downcasing,trimming,tokenizing,parsing等)都是某些字符串类的成员函数。
请注意,STL的std::string
没有所有这些方法。 STL是面向对象的 - 字符串对象的状态和实现细节被很好地封装,只有一个小的,正交的接口暴露给世界。人们过去作为成员函数包含的所有疯狂操作现在都被委托给非成员函数。
这很强大,因为这些函数现在可以在任何字符串类上工作,它暴露相同的接口。如果您对大多数事物使用STL字符串,并且根据您的程序的特性调整专业版本,则不必复制成员函数。你只需要实现基本的字符串接口,然后你可以重复使用所有那些疯狂的操作。
有些人将这种混合方法称为通用编程。它仍然是面向对象的编程,但它远离了许多人与OOP关联的“一切都是成员函数”的心态。
答案 16 :(得分:0)
恕我直言,我觉得OOP概念并不真正适合大数据的需求,因为OOP假定所有东西都保存在内存中(对象和成员变量的概念) 。当将OOP例如用于大图像处理时,这总是导致内存需求大且应用繁重。取而代之的是,C的简单性可以与密集的并行I / O结合使用,从而使应用程序更高效,更易于实现。 现在是2019年。我正在写这条消息...一切可能在一年中发生变化! :)