在用 C++ 编码几年后,我最近获得了一份在嵌入式领域用 C 编码的工作。
撇开在嵌入式领域摒弃 C++ 是对还是错的问题,C++ 中的一些特性/习语我会错过很多。仅举几个:
- 通用的、类型安全的数据结构(使用模板)。
- RAII。特别是在具有多个返回点的函数中,例如不必记住在每个返回点上释放互斥锁。
- 一般的析构函数。即,您为 MyClass 编写一次 d’tor,然后如果 MyClass 实例是 MyOtherClass 的成员,则 MyOtherClass 不必显式取消初始化 MyClass 实例 - 它的 d’tor 会自动调用。
- 命名空间。
你从 C++ 迁移到 C 的经历是什么?
您为您最喜欢的 C++ 特性/习语找到了哪些 C 替代品?你有没有发现任何你希望 C++ 拥有的 C 特性?
原文由 george 发布,翻译遵循 CC BY-SA 4.0 许可协议
在一个嵌入式项目上工作,我曾经尝试过使用所有 C 语言,但就是受不了。它太冗长了,以至于很难阅读任何内容。另外,我喜欢我编写的针对嵌入式优化的容器,它必须变得更不安全,更难修复
#define
块。C++ 中的代码如下所示:
变成:
许多人可能会说这很好,但是如果您必须在一行中执行多个“方法”调用,那就太荒谬了。两行 C++ 将变成五行 C(由于 80 字符行长度限制)。两者都会生成相同的代码,所以它不像目标处理器关心!
有一次(早在 1995 年),我尝试为多处理器数据处理程序编写大量 C 语言。每个处理器都有自己的内存和程序的那种。供应商提供的编译器是 C 编译器(某种 HighC 衍生产品),它们的库是封闭源代码,因此我无法使用 GCC 来构建,并且它们的 API 的设计理念是您的程序主要是初始化/进程/terminate 种类繁多,因此处理器间的通信充其量只是初级的。
在我放弃之前大约一个月,我找到了 cfront 的副本,并将其破解到 makefile 中,以便我可以使用 C++。 Cfront 甚至不支持模板,但 C++ 代码要清晰得多。
通用的、类型安全的数据结构(使用模板)。
C 与模板最接近的事情是声明一个包含大量代码的头文件,如下所示:
然后用类似的东西把它拉进去:
请注意,这不适用于复合类型(例如,没有队列
unsigned char
),除非您首先创建typedef
。哦,记住,如果这段代码实际上并没有在任何地方使用,那么你甚至不知道它在语法上是否正确。
编辑: 还有一件事:您需要 手动 管理代码的实例化。如果您的“模板”代码不 都是 内联函数,那么您必须进行一些控制以确保事物只被实例化一次,这样您的链接器就不会吐出一堆“Foo 的多个实例”错误.
为此,您必须将非内联内容放在头文件的“实现”部分中:
然后,在 每个模板变体 的所有代码中的 一个 地方,您必须:
此外,这个实现部分需要在标准 之外
#ifndef
/#define
/#endif
一连串,因为你可以在另一个头文件中包含模板头文件,之后需要在.c
文件中实例化。是的,它很快就变得丑陋了。这就是为什么大多数 C 程序员甚至都不尝试的原因。
RAII。
特别是在具有多个返回点的函数中,例如不必记住在每个返回点上释放互斥锁。
好吧,忘记你漂亮的代码并习惯你所有的返回点(除了函数的结尾) 是
goto
s:一般的析构函数。
即,您为 MyClass 编写一次 d’tor,然后如果 MyClass 实例是 MyOtherClass 的成员,则 MyOtherClass 不必显式取消初始化 MyClass 实例 - 它的 d’tor 会自动调用。
对象构造必须以相同的方式显式处理。
命名空间。
这实际上是一个简单的解决方法:只需在 每个 符号上添加一个前缀。这是我之前谈到的源代码膨胀的主要原因(因为类是隐式命名空间)。 C 的人一直生活在这,好吧,永远,可能不会看到有什么大不了的。
YMMV