嵌入式系统的面向对象是不好的,为什么?

时间:2010-07-18 05:35:23

标签: c++ c embedded

许多嵌入式工程师使用c ++,但有些人认为它很糟糕,因为它是“面向对象的”?

面向对象是否真的对嵌入式系统有害,如果是这样,为什么会出现这种情况呢?

编辑:这是一个快速参考,询问:

  

所以我们   更喜欢人们不要使用除...,malloc ......或其他对象   携带大的定向练习   罚。

我想问题是嵌入式系统环境中被认为是重量级的对象?这里的一些答案表明他们是,有些人认为他们不是。

11 个答案:

答案 0 :(得分:13)

从表面上看,动态内存分配与面向对象的软件设计是完全独立的概念,因此它是完全错误的。您可以使用面向对象的设计,而不是使用动态内存分配。

实际上,你可以在一定程度上在C中执行OO(这就是Linux内核所做的)。许多嵌入式开发人员不喜欢C ++的真正的原因是它非常复杂,很难在其中编写直接且可预测的代码。 Linus a good recent rant解释了为什么他不喜欢C ++(我承诺,它比他的old one更好,更合理)。可能大多数人都没有很清楚地表达出来。

答案 1 :(得分:13)

虽然我不确定它是否回答了您的问题,但我可以总结一下我以前的公司源代码是纯C的原因。

首先值得总结一下情况:

  • 我们希望编写大量“核心”代码,这些代码可以在大量ARM嵌入式系统(大多数是中档手机;智能手机和运行不同年龄的RTOS的手机)中实现高度便携性。
  • 平台通常有一个可行的C编译器,但有些例如不支持浮点“双”。
  • 在某些情况下,平台有一个合理的标准库实现,但在很多情况下它没有。
  • C ++编译器在大多数平台上都不可用,并且它可用于支持C ++标准库,STL或异常变化很大。
  • 调试器通常不可用(您可以发送调试printfs的串口被视为奢侈品)
  • 我们总是可以访问合理数量的内存,但往往没有合理的malloc()实现

鉴于此,我们完全使用C语言,甚至只使用了一组受限制的C 89.结果代码非常便于携带。我们经常使用面向对象的概念。

这些天“嵌入式”是一个非常广泛的定义。它涵盖了从没有RAM或C编译器的8位微处理器到基本上高端PC(尽管没有运行Microsoft Windows)的所有内容 - 我不知道您的项目/公司在该范围内的位置。

答案 2 :(得分:6)

是什么让你说C ++是面向对象的? C ++是多范式的,并非由于其开销,C ++提供的所有功能对嵌入式市场都很有用。 (所以......只是不要使用这些功能!问题解决了!)

答案 3 :(得分:4)

“面向对象”的任何内容都不利于嵌入式系统。 OO只是一种思考软件的方式。

对于嵌入式系统来说,最糟糕的是,他们通常会使用不太复杂的调试器,而C ++会在你背后做很多疯狂的事情,可以这么说。那些难以访问的代码将让你疯狂。

答案 4 :(得分:4)

面向对象非常适合嵌入式系统。它主要关注封装,数据隐藏和代码共享。可以使用面向对象的嵌入式系统,而无需划分或动态内存分配。

分区和动态内存分配是嵌入式系统的敌人,无论面向对象,面向数据还是程序编程。这些概念可能会也可能不会用于面向对象设计的实现。

面向对象允许UART类在不知道Message对象内容的情况下传输Message对象的实例。 Message可以是基类,有几个后代类。

C ++语言通过允许构造函数,复制构造函数和析构函数来帮助促进嵌入式系统中的安全编码,这些编译器只能在最高纪律的C语言嵌入式系统中记住。

异常处理也是使用C语言工作的一种痛苦。 C ++提供了嵌入到语言中的更好的工具。

C ++语言提供了用于编写公共代码以处理不同数据类型的模板。典型的例子是环形缓冲区或循环队列。在C语言中,必须使用“指向void的指针”,以便可以传递任何对象。 C ++提供了一个模板,因此可以编写一个使用不同数据类型的Circular_Queue类,并具有更好的编译时类型检查。

继承允许更好的代码共享。共享代码被考虑到基类中,并且可以创建共享相同功能的子类;通过继承。

C语言提供函数指针。 C ++语言为函数对象(具有属性的函数指针)提供了工具。

抱歉,我不喜欢那些将嵌入式系统限制为C语言的人因为谣言和对C ++的知识和经验不足。

答案 5 :(得分:3)

面向对象的设计本身并不错。答案在于你的引用。特别是在实时嵌入式系统中,您希望尽可能轻松高效地编写代码。引用中提到的内容(对象,除法,动态内存分配)相对较重,通常可以用更简单的替代方法替换(例如,使用位操作来近似除法,在堆栈上分配内存或使用静态池)来改进在时间关键系统中的表现。

答案 6 :(得分:2)

C ++的设计理念是不支付你不使用的东西。因此,除了缺乏良好的嵌入式编译器之外,没有真正的理由。

也许CFront可以将C ++编译成C,其中已经无数的编译器......

编辑:Comeau编译器将C ++转换为普通C,因此no-compiler参数不成立。

答案 7 :(得分:2)

正如其他人所说,'嵌入式'涵盖了广泛而多样的硬件/软件选项。但...

您给出的报价将给微控制器嵌入式类型带来颤抖。动态分配是禁忌,如果您有错误,则会以不可预测的方式使系统崩溃。由于他们在执行时间永远,因此非常不鼓励分歧。只是因为它们倾向于随身携带许多“东西”,所有这些“东西”占用空间,微控制器没有任何物体,因此不鼓励使用物体。

我认为嵌入式是一个小而具体的项目,您不必担心可扩展性或可移植性。您可以使用C语言编写干净的代码,这些代码仅可以完美地执行您希望设备执行的操作。您选择一个芯片系列,这样您就可以在不同的硬件选项中移动(几乎相同)相同的代码,只需对您的写入端口进行微调或初始化配置保险丝。

因此,您无需定义

  1. 4轮运输
  2. 汽车
  3. 丰田
  4. 因为你只是在丰田公司工作。并且凯美瑞和卡罗拉之间的加速度差异作为常数存储在寄存器中。

答案 8 :(得分:1)

编程始终是为工作使用正确的工具。没有轻拍的答案,在嵌入式世界尤其如此。如果你想要熟练掌握嵌入式开发,你就会像C语言一样熟悉C语言。

答案 9 :(得分:1)

如上所述,它背后的面向对象/ malloc / math会带来什么损失 - 代码大小和CPU周期都是嵌入式的。

作为一个例子,在循环中包含sqrt()函数在递归计算中增加了很多开销,我们不得不将其删除并对其进行快速近似,如果我没记错的话,使用查找表。

一定要使用您喜欢的任何工具/语言,但您至少需要抬起盖子并检查背后产生多少额外代码。

答案 10 :(得分:-1)

首先,让我们将其分开:

  

因此我们更希望人们不要使用除法...,malloc ...或其他会带来巨大损失的面向对象的实践。

除法和malloc并不是面向对象编程所独有的,它们也存在于过程语言中(并且可能是功能性的,以及您可能想到的任何其他范式)。

在嵌入式系统上,如果分区和malloc的资源足够有限,那么这可能是一个问题,这是事实,但是无论您使用哪种编程范例,它们都将成为问题。


主要问题“面向对象对嵌入式系统不利吗?”。

首先,“面向对象”的范围很广。对于实际含义,有些人有相互矛盾的想法。有一个极简主义的定义,其中对象本质上只是函数(或“方法”)和数据的捆绑,还有一个更“纯粹”的定义,其中还包括继承和多态性等功能。

如果采用OOP的最低限度定义,则否-OOP对于嵌入式系统来说还不错。它确实取决于语言,但是使用对象和不使用对象一样便宜(在某些情况下可能更便宜)是完全可能的。在C ++中,一个对象(没有virtual方法,我将在稍后介绍)占用的内存不会超过其各个字段(如果它们不是对象的一部分)所占用的内存。在C ++中,对象的(大小)等于其部分的(大小)之和。

但是,如果您采用OOP的“清教徒”观点,并坚持包括继承和多态性,那么答案是“是的,这很不好”。继承可能不那么在乎(取决于语言),但是通过virtual方法进行的多态性无疑是一种内存消耗。 virtual函数通常通过维护一个“ vtable”(虚拟方法表)来实现,该表存储指向正确函数的指针,每个对象必须存储一个指向其vtable的指针以启用动态调度(调用虚拟函数的过程) )正常工作。在某些情况下,与不需要继承的解决方案相比,继承可以使用更多的内存-通常,在将继承与组合进行比较时,组合有时会使用较少的内存。

最后一点,特别是对于C ++而言(因为这是人们谈论嵌入式系统上使用OOP时通常的意思)。人们经常说“ C ++在背后做一些奇怪的事情” –它在做某些事情时在查看代码时不会立即使这些事情变得显而易见,例如生成我前面提到的vtable,但是它并没有做这些事情您的背部”以阻止您这样做,是因为这些只是实现所使用功能的必要条件。总体而言,“幕后”几乎没有有害的事情发生,并且它所做的事情并非完全是神秘的或神秘的,它们通常是众所周知的,并且是程序员进行编程时应注意的事情嵌入式系统。如果您对它们一无所知,那么您就不会正确地了解自己的工具,应该对它们进行更多研究。

说了这么多,请记住,人们可以自由选择使用或不使用哪些语言功能。避免使用诸如虚拟函数之类的更昂贵的功能是绝对有意义的,但是仅仅因为它具有一些昂贵的完全可选功能(例如virtual功能)-那只是把婴儿扔出去的洗澡水。