简体   繁体   English

重构C ++代码以使用前向声明

[英]Refactoring C++ code to use forward declarations

I've got a largeish codebase that's been around for a while and I'm trying to tidy it up a bit by refactoring it. 我有一个很长的代码库已经存在了一段时间,我试图通过重构来整理它。 One thing I'd like to do is find all the headers where I could forward declare members, instead of including the entire header file. 我想做的一件事是找到我可以转发声明成员的所有标题,而不是包括整个头文件。

This is a fairly labour intensive process and I'm looking for a tool that could help me figure out which headers have members that could be forward declared. 这是一个相当费力的过程,我正在寻找一个工具,可以帮助我找出哪些标题包含可以向前声明的成员。

Is there a compiler setting that could emit a warning or suggestion that the following code could use a forward declaration? 是否有编译器设置可能会发出警告或建议以下代码可以使用前向声明? I'm using the following compilers icc, gcc, sun studio and HP's aCC 我正在使用以下编译器icc,gcc,sun studio和HP的aCC

Is there a standalone tool that could do the same job? 是否有可以完成相同工作的独立工具?

#include "Foo.h"
...//more includes

class Bar {
.......
private:
    Foo* m_foo;
};

Anything involving the precise analysis of C++ requires essentially an entire C++ front end somewhere (otherwise you won't get answers, or they'll be wrong, and that works badly when you have "largish" applications). 任何涉及C ++精确分析的东西都需要一个完整的C ++前端(否则你就不会得到答案,或者它们会出错,而且当你有“大”的应用程序时,它会很糟糕)。 There aren't many practical answers available here. 这里没有很多实际答案。

Already mentioned is GCCXML is a GCC-derived package, so it has the requisite C++ front end. 已经提到的是GCCXML是一个GCC派生的包,所以它有必要的C ++前端。 It produces XML, thus it will produce a LOT of output that you'll have to read back in to form "the in memory data structure" suggested in another answer. 它产生XML,因此它将产生大量输出,你必须重新读回来形成另一个答案中建议的“内存数据结构”。 Its unfortunate that GCCXML builds that memory data structure already, then exports it as XML, and forces you to build it again. 不幸的是,GCCXML已经构建了内存数据结构,然后将其导出为XML,并迫使您再次构建它。 Of course, you could just use GCC, which builds the in memory data structure, but then you have to hack GCC to be what you want, and it really, really wants to be a compiler. 当然,你可以使用GCC来构建内存数据结构,但是你必须破解GCC才能成为你想要的东西,而且它确实真的想成为一个编译器。 That means you'll have a fight on your hands to bend it to your will (and explains why GCCXML exists: most people don't want that fight). 这意味着你将在你的手上进行战斗以使其符合你的意愿(并解释为什么存在GCCXML:大多数人不想要那场斗争)。

Not mentioned is the Edison Design Group C++ (EDG) front end, which builds that in memory data structure directly. 未提及的是Edison Design Group C ++(EDG)前端,它直接在内存数据结构中构建。 It is a front end; 这是一个前端; you'll have to do all the analysis stuff yourself but your task may be simple enough so that isn't hard. 你必须自己做所有的分析工作,但你的任务可能很简单,所以这并不难。

The last solution I know is mine: C++ FrontEnd for DMS . 我知道的最后一个解决方案是我的: C ++ FrontEnd for DMS DMS is foundation for building program analysis, and its C++ FrontEnd is a complete Front end for C++ (eg, does everything the GCC and Edison front ends do: parsing, tree building, name/type resolution). DMS是构建程序分析的基础,它的C ++ FrontEnd是C ++的完整前端(例如,GCC和Edison前端的所有内容都做:解析,树构建,名称/类型解析)。 And you'll have to code your special analysis much the way you would for GCCXML and EDG by walking over the "in memory" datastructures produced by DMS. 而且你必须通过遍历DMS生成的“内存”数据结构,对GCCXML和EDG的方式编写特殊的分析代码。

What is really different is that DMS could then be used to actually modify your source code by updating those in memory data structures, and regenerate compilable code from those memory structures, including the original comments. 真正不同的是,DMS可以用于通过更新内存数据结构中的源代码来实际修改源代码,并从这些内存结构(包括原始注释)重新生成可编译代码。

I'm not sure you'll find anything that does this out-of-the box, but one option would be to write a script using Python and the pygccxml package that could do some of this analysis for you. 我不确定你会发现任何开箱即用的东西,但一个选择是使用Python和pygccxml包编写一个脚本,它可以为你做一些分析。

Basically you'd use pygccxml to build an in-memory graph of your source code, then use it to query your classes and functions to find out what they actually need to include to function. 基本上你会使用pygccxml来构建源代码的内存中的图形,然后使用它来查询你的类和函数,以找出它们实际需要包含的功能。

So for example you could ask each class, give me the members that are pointer types: then for each of those pointer types you could work out if a real instance (non pointer) of the class was used in the interface, and if not you could mark it as a candidate for forward declaration. 因此,例如,您可以询问每个类,给我指针类型的成员:然后对于每个指针类型,如果在接口中使用了类的实例(非指针),则可以解决,如果不是,可以将其标记为前瞻性声明的候选人。

The downside is that the script would take some time to get right so the cost might outweigh the benefits but it would be an interesting exercise at least. 缺点是脚本需要一些时间才能正确,所以成本可能超过好处,但至少这将是一个有趣的练习。 You could post your code to Github if you got something that worked and maybe others would find it useful. 你可以将代码发布到Github,如果你有一些有用的东西,也许其他人会觉得它很有用。

What you could do is call gcc with -MM. 你可以做的是用-MM调用gcc。 This will produce dependency files that Make can read. 这将生成Make可以读取的依赖文件。 Instead of having make use them, you could parse them (with perl, or something) to determine which includes are needed and which could be replaced with forward declarations. 您可以解析它们(使用perl或其他东西)而不是使用它们来确定哪些包含是必需的,哪些可以用前向声明替换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM