gpt4 book ai didi

c++ - 如何更新旧的 C 代码?

转载 作者:IT老高 更新时间:2023-10-28 12:32:39 26 4
gpt4 key购买 nike

关闭。这个问题是opinion-based .它目前不接受答案。




3年前关闭。










锁定。这个问题及其答案是locked因为这个问题是题外话,但具有历史意义。它目前不接受新的答案或互动。








本周我的工作一直在研究一些 10 年前的 C 代码,在实现了一些更改后,我去找老板问他是否还需要做其他事情。那是他扔炸弹的时候。我的下一个任务是浏览大约 7000 行代码并理解更多代码,并对代码进行一定程度的模块化。我问他希望源代码如何模块化,他说开始把旧的 C 代码放到 C++ 类中。

作为一名优秀的员工,我点了点头,是的,然后回到我现在坐的办公 table 前,想知道到底如何使用这些代码,并将其“模块化”。它已经包含在 20 个源文件中,每个文件都有自己的用途和功能。此外,还有三个“主要”结构。这些结构中的每一个都有 30 多个字段,其中许多是其他较小的结构。试图理解它完全是一团糟,但几乎程序中的每个函数都传递了一个指向结构之一的指针并大量使用该结构。

有什么干净的方法可以让我把它硬塞进类吗?如果可以做到,我决心去做,我只是不知道如何开始。

最佳答案

首先,您很幸运,您的老板认识到代码重构可以成为一项长期的成本节约策略。

我已经做过很多次了,即将旧的 C 代码转换为 C++。好处可能会让你大吃一惊。完成后,最终代码可能是原始大小的一半,并且更易于阅读。此外,您可能会在此过程中发现棘手的 C 错误。以下是我将在您的情况下采取的步骤。小步骤很重要,因为在重构大量代码时,您无法从 A 跳转到 Z。您必须经历一些小的中间步骤,这些步骤可能永远不会部署,但可以在您使用的任何 RCS 中进行验证和标记。

  • 创建回归/测试套件。 每次完成对代码的一批更改时,您都将运行测试套件。你应该已经有了它,它不仅对这个重构任务有用。花点时间让它全面。创建测试套件的练习将使您熟悉代码。
  • 分支项目在您选择的版本控制系统中。有了测试套件和操场分支,您将有权对代码进行大量修改。你不会害怕打破一些鸡蛋。
  • 将这些结构字段设为私有(private)。 这一步只需要很少的代码更改,但可以获得很大的返回。一次进行一个字段。尽量使每个字段private (是,或 protected ),然后隔离访问该字段的代码。最简单、最非侵入性的转换是使该代码成为 friend function .还考虑使该代码成为一种方法。将代码转换为方法很简单,但您还必须转换所有调用站点。一个不一定比另一个好。
  • 将参数缩小到每个函数。 任何函数都不太可能需要访问作为其参数传递的结构体的所有 30 个字段。而不是传递整个结构,只传递所需的组件。如果一个函数实际上似乎需要访问结构的许多不同字段,那么这可能是转换为实例方法的一个很好的候选者。
  • 构造尽可能多的变量、参数和方法。 很多旧的 C 代码无法使用 const宽松地。自下而上(即调用图的底部)扫过一遍,您将为代码添加更强的保证,并且您将能够从非变体中识别变体。
  • 用引用替换指针 哪里明智。这一步的目的与更像 C++ 无关,只是为了更像 C++。目的是识别永远不会出现的参数 NULL并且永远不能重新分配。将引用视为编译时断言,它表示这是有效对象的别名,并表示整个当前范围内的同一对象。
  • 替换 char*std::string .这一步应该是显而易见的。您可能会大大减少代码行数。另外,用一行代码替换 10 行代码很有趣。有时,您可以消除旨在执行 C++ 中标准的 C 字符串操作的整个函数。
  • 将 C 数组转换为 std::vectorstd::array .同样,这一步应该是显而易见的。这种转换比从 char 的转换简单得多。至 std::string因为std::vector的接口(interface)和 std::array旨在匹配 C 数组语法。好处之一是您可以消除额外的 length变量传递给与数组一起的每个函数。
  • 转换 malloc/freenew/delete .这一步的主要目的是为以后的重构做准备。仅从 malloc 更改 C 代码至 new不会直接给你带来很多好处。这种转换允许您向这些结构添加构造函数和析构函数,并使用内置的 C++ 自动内存工具。
  • 替换本地化 new/deletestd::auto_ptr 的操作家庭。 此步骤的目的是使您的代码异常安全。
  • 在通过冒泡处理返回码的任何地方抛出异常。 如果 C 代码通过检查特殊错误代码来处理错误,然后将错误代码返回给它的调用者,依此类推,将错误代码向上传递到调用链,那么该 C 代码可能是使用异常的候选者。这种转换实际上是微不足道的。简单 throw最低级别的返回代码(C++ 允许您抛出任何您想要的类型)。插入一个 try{} catch(){}处理错误的代码中的语句。如果没有合适的地方来处理错误,可以考虑包裹main()的主体。在 try{} catch(){}声明并记录它。

  • 现在退后一步,看看您对代码进行了多少改进,而无需将任何内容转换为类。 (是的,是的,从技术上讲,您的结构已经是类。)但是您还没有触及 OO 的皮毛,却设法极大地简化和巩固了原始 C 代码。

    您是否应该将代码转换为使用具有多态性和继承图的类? 我拒绝。 C 代码可能没有适合 OO 模型的整体设计。请注意,上述每个步骤的目标与将 OO 原则注入(inject) C 代码无关。目标是通过强制执行尽可能多的编译时约束以及消除或简化代码来改进现有代码。

    最后一步。

    考虑添加基准 这样你就可以在完成后把它们展示给你的老板。不仅仅是性能基准。比较代码行数、内存使用情况、函数数量等。

    关于c++ - 如何更新旧的 C 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3007707/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com