【问题标题】:Do people actually do OO in C? [closed]人们真的用C语言做OO吗? [关闭]
【发布时间】:2012-08-08 22:45:19
【问题描述】:

可以通过显式传递this 指针在C 中模拟成员函数。可以通过在每个对象中显式存储指向函数指针全局数组的指针来模拟虚函数。很好。

现在我的问题是,人们真的会这样做吗?我想知道是否值得教授这种技术,因为我不想教 C 新生在现实世界中几乎从未使用过的东西。

(我需要为已经熟悉 OOP 的人完成为期两周的 C 入门课程的最后一天。)

是否有任何相关项目、库或框架以所述方式在 C 中模拟 OO?

【问题讨论】:

  • 即使它使用了(并且afaik,它是),这是新生需要在C课程中学习的东西吗?
  • @jalf 这并不难理解。如果有人真正了解 C 的基础知识,一段时间后他最终会偶然发现这一点。他会明白的。
  • 我同意jalf的观点,我认为这不是应该提早提出的东西,我个人认为根本没有必要。 Imo,如果您想编程 OO,请使用 OO 语言。但要回答您关于库的问题:查看 GLib 和 GObject。
  • @H2CO3 当然,这不难理解。但是正如您所说,一旦您了解了 C,如果需要,您将自行解决所有问题。所以我在质疑是否值得在大一 C 班上教

标签: c oop virtual-functions


【解决方案1】:

我在 C 方面有大约 20 年的经验。它是我学习的第一个编译语言,我从不需要继续前进,所以它一直是 C,而且只有 C。我经常在工作和家里编写代码。我已经发布了一个无锁数据结构库。我认为我是一个称职的 C 程序员。

关于您的问题,OO 包含许多概念。例如,一个是实例化,例如具有 new() 和 delete() 以及给定实体(堆栈、列表等)的实例的库。 C 支持这一点,当然,它是一种非常实用且有用的方法。我已经使用这种方法大约十五年了。

多年前,我开始尝试另一个在 C++ 中得到很好支持的 OO 概念,即继承。我想要一个包含其他实体的实体。然后问题是暴露所包含实体的 API。你可以这样做,但事实是,C 语言并没有自然地表达这样的概念和方法。这不是我现在使用的东西。

我的建议是;刀就是刀,叉就是叉。您可以将其中一个用作另一个,但效果不佳。 C 自然不支持某些(重要的)OO 概念,例如继承。不要试图让 C 做这些事情。如果你想这样做,请使用 C++。

【讨论】:

    【解决方案2】:

    是的,他们有。

    是否有任何相关项目、库或框架以所述方式在 C 中模拟 OO?

    我不会因为没有一流的语言支持而称其为“模拟”。见GObject

    【讨论】:

      【解决方案3】:

      很多项目在 C 代码库中使用面向对象的范例。由于各种原因,他们不直接使用 CPP。对于系统级或性能密集型项目,其他语言不适合。所以这是cpp和c之间的战斗。

      为什么人们在 C 中模仿 OO 而不是完整的 CPP 是激烈争论的话题。 Linus torvalds 曾经说过一句名言,CPP 编译器是不值得信赖的。他对 CPP 生成的代码缺乏信心。

      Linux 内核是在 C 中实现 OO 设计模式的一个很好的例子。您可以在这个 lwn.net 文章系列中了解 Linux 内核是如何做到的:

      part1

      part2

      互联网上有一个广泛的免费文档,其中涵盖了用 C 语言实现的全方位 OO 设计模式。

      ooc.pdf

      您可以在同一条道路上找到许多其他项目。

      例子:

      pjsip

      sofia

      【讨论】:

        【解决方案4】:

        它可能不会在实践中使用,但是学习成员函数和以对象为第一个参数的函数之间的等价概念是非常有价值的。将这个概念牢记在心将帮助他们解决今后将遇到的许多问题。

        日复一日,我看到人们在 Stack Overflow 上提出问题,为什么指向将成员函数传递给需要函数指针的东西不起作用,诸如此类。他们认为成员函数只是作为对象一部分的一些神奇函数,使整个情况过于复杂。如果他们已经意识到成员函数等同于将对象作为第一个参数的函数,那么他们遇到的问题(即调用方法他们将不知何故需要成员函数指针和对象),如以及可能的解决方案(以某种方式单独传递对象,或进行某种捕获对象的闭包)变得显而易见。显然,太多人只是假装 OO 是“神奇的”而不理解这一点。

        在函数式编程中,我们经常教人们如何纯粹根据函数操作来编写数据结构和局部变量以及所有这些东西。并不是说这是实用的——它可能效率低下——但这让他们对函数的力量印象深刻。它可以帮助他们以不同的方式理解事物。如果他们写了一个编译器或其他东西,也许在路上,这些等价物会派上用场。

        计算机科学就是关于等价和约简,以及如何从一个问题的角度考虑另一个问题。我们将 SAT-3 简化为子集和,并不是因为这实际上是我们实际解决 SAT-3 问题的方式,而是因为这告诉我们子集和是 NP 完全的。

        每隔一段时间,我就会遇到一段由其他人编写的代码,其中非实例方法将指向结构的指针作为参数,然后我看到了一个模式,并且我的脑海中出现了一个灯泡,我说,啊哈,这可以重新分解为实例方法,因为我知道这种等价性。所以你看,知道这些等价性也有助于我们编写更好、更简单的代码。

        【讨论】:

          【解决方案5】:

          查看 TI 的“DSP 算法标准”/xDAIS 框架。

          有一个通用的 C API,每个符合 DSP 算法的实现都会实现(抱歉重言式)。对所有这些“艺术”的需求源于 DSP 世界中常见的几个问题:

          • 相对较小的 RAM
          • 多个数据通道(通常是并行/并发)
          • 复杂的算法使用模式
          • 我忘记的其他事情

          标准和框架旨在让 DSP 工程师更容易使用 3rd 方 DSP 算法。

          有一个接口可以配置算法实例并查询其内存需求(基于配置),并且有实际管理内存的支持函数。

          可以临时分配一些内存区域(暂存区),并在算法实例处于活动状态时将其分配给算法实例,在算法实例处于非活动状态时将其取走并提供给另一个实例,从而有效共享。

          还有将实例内存缓冲区移动到碎片整理内存的功能(和 API)。

          还有更多,但我需要重新阅读文档以回忆细节。

          参见IALG_*()ALG_*() 接口方法示例。

          此外,还有一些工具可以验证通用 API 的实现。第三方可以请求 TI 对其进行官方验证。

          一些相关链接:spru352g.pdfspru360e.pdf

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-01-17
            • 2018-05-14
            • 2010-12-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多