是否有工具将“覆盖”标识符添加到现有C ++代码中

时间:2011-09-03 14:28:49

标签: c++ override c++11

任务

我正在尝试找出如何最好地将C ++ 0x的override标识符添加到已经覆盖在大量C ++代码中的所有现有方法中,而不是手动执行。

(我们有很多,几十万行代码,并且手动完成这将是一个完全不起作用的。)

当前的想法

我们的编码标准说我们应该在派生类中对所有隐式虚方法添加virtual关键字,即使严格不必要(以帮助理解)。

因此,如果我自己编写脚本,我会编写一个脚本来读取所有标题,找到所有以virtual开头的函数,并在下面的分号前插入override。然后在支持override的编译器上编译它,并修复基类中的所有错误。

但我真的不愿意使用这种本土化的方式,因为:

  • 显然会很乏味且容易出错。
  • 并非每个人都记得,每次都要添加虚拟关键字,因此这种方法会错过一些现有的覆盖

是否有现有工具?

那么,是否有一个工具可以解析C ++代码,检测覆盖的现有方法,并将override附加到它们的声明中?

(我知道静态分析工具,例如PC-lint,它们会警告那些看起来应该覆盖的函数。我所追求的是实际上会使我们的代码变得混乱的东西,以便将来的错误覆盖将在编译时检测,而不是稍后在静态分析中检测到)

(如果有人想要指出C ++ 03不支持'覆盖'......在实践中,我将添加一个宏,而不是实际的“覆盖”标识符,以使用我们的不支持此功能的旧编译器上的代码。所以在添加标识符之后,我会运行一个单独的脚本来替换它我们将要使用的任何宏...)

提前致谢...

5 个答案:

答案 0 :(得分:14)

LLVM项目正在开发一个名为“cpp11-migrate”的工具,该工具目前具有以下功能:

  • 将循环转换为基于范围的for循环
  • 将空指针常量(如NULL0)转换为C ++ 11 nullptr
  • 使用auto类型说明符
  • 替换变量声明中的类型说明符
  • override说明符添加到适用的成员函数

此工具记录为here,应作为clang 3.3的一部分发布。 但是,您可以下载源代码并立即自行构建。

修改

更多信息:

编辑2:2013-09-07

“cpp11-migrate”已重命名为“clang-modernize”。对于Windows用户,它现在包含在新的LLVM Snapshot Builds

答案 1 :(得分:7)

我们的DMS Software Reengineering Toolkit及其支持C ++ 11的C++ Front End可以执行此操作。

DMS是用于任意编程语言的通用程序转换系统; C ++前端允许它处理C ++。 DMS解析,构建准确的AST和符号表(这对C ++来说很难),提供对查询AST节点和树的属性的支持,允许在树上进行过程转换和源到源转换。完成所有更改后,可以重新生成修改后的树,并保留注释。

您的问题需要找到派生的虚拟方法并进行更改。执行此操作的DMS源到源转换规则类似于:

    source domain Cpp.  -- tells DMS the following rules are for C++

    rule insert_virtual_keyword (n:identifier, a: arguments, s: statements):
       method_declaration -> method_declaration " =
       " void \n(\a) { \s } "  ->  " virtual void \n(\a) { \s }"
       if is_implicitly_virtual(n).

此类规则与语法树匹配,因此它们不会与注释,字符串或其他内容不匹配。有趣的引号不是C ++字符串引号;它们是元引号,允许规则语言知道它们内部的内容必须被视为目标语言(“Cpp”)语法。反斜杠是目标语言文本的转义,允许匹配任意结构,例如,\ a表示需要“a”,它被定义为语法类别“arguments”。

你需要更多的规则来处理函数返回非空结果的情况,等等,但你不需要很多。

有趣的部分是实现控制转换应用程序的谓词(返回TRUE或FALSE):is_implicitly_virtual。该谓词采用(抽象语法树)方法名称n。 这个谓词将参考完整的C ++符号表来确定n究竟是什么。我们已经知道它是一种方法,只是它的语法设置,但我们想知道在什么类的上下文中。 符号表提供方法和类之间的链接,类的符号表信息告诉我们类继承的内容,以及这些类,它们包含哪些方法以及如何声明它们,最终导致发现(或不)父类方法是虚拟的。执行此操作的代码必须实现为针对C ++符号表API的过程代码。然而,所有艰苦的工作都已完成;符号表是正确的,包含对所需的所有其他数据的引用。 (如果您没有此信息,则无法通过算法决定,并且任何代码更改都可能是错误的。)

DMS过去曾使用程序转换对C ++代码进行大量更改。(查看网站上的论文页面,了解C ++重新架构主题)。

(我不是C ++专家,只是DMS架构师,所以如果我有错误的细节,请原谅。)

答案 2 :(得分:2)

几个月前我做了类似这样的事情,大约有3 MB的代码,而你说“手动完成它将是一个完全不起作用的”,我认为这是唯一的方法。原因是您应该将override关键字应用于预期的原型以覆盖基类方法。任何添加它的工具都会将它放在实际覆盖基类方法的原型上。编译器已经知道那些方法,所以添加关键字不会改变任何东西。 (请注意,我对新标准并不十分熟悉,我假设override关键字是可选的。至少从VS2005开始,Visual Studio支持覆盖。)

我在头文件中搜索了“virtual”来查找大部分内容,我偶尔会发现另一个缺少override关键字的原型。

我发现了两个错误。

答案 3 :(得分:0)

Eclipse CDT具有可用的C ++解析器和语义实用程序。最新版本IIRC还具有覆盖方法的标记。

编写一个基于此的插件并在适当的时候重写代码以包含override标记不需要太多代码。

答案 4 :(得分:0)

一个选择是

启用建议覆盖编译器警告,然后编写脚本     可以将override关键字插入发出的警告所指向的位置