是否有工具可以解析 C++ 项目并决定头文件是否自给自足:即,如果文件 Foo.cc(或 Foo.h)提到某个类 Bar(例如向量),那么它本身包含一个定义该类的头文件(定义 Bar 的文件,例如<vector>
)?
编辑:我想澄清一下:如果头文件 Foo.h 提到向量并且其中一个包含已经包含的向量,编译器会很高兴。我不想要那个。如果 Foo.h 完全提到了向量,它应该直接包含它而不依赖于另一个标题。编译器能捕捉到这个吗?
是否有工具可以解析 C++ 项目并决定头文件是否自给自足:即,如果文件 Foo.cc(或 Foo.h)提到某个类 Bar(例如向量),那么它本身包含一个定义该类的头文件(定义 Bar 的文件,例如<vector>
)?
编辑:我想澄清一下:如果头文件 Foo.h 提到向量并且其中一个包含已经包含的向量,编译器会很高兴。我不想要那个。如果 Foo.h 完全提到了向量,它应该直接包含它而不依赖于另一个标题。编译器能捕捉到这个吗?
编译器将为您执行此操作。由于这个原因,许多 C++ 风格指南强烈建议所有 .cpp 文件都应包含相应的标头作为第一个实质性包含指令。
我为此使用了一个脚本。这是一个简化版本:
#!/usr/bin/env bash
# hcheck: Check header file syntax (works on source files, too...)
if [ $# -eq 0 ]; then
echo "Usage: $0 <filename>"
exit 1
fi
for f in "$@" ; do
case $f in
*.c | *.cpp | *.cc | *.h | *.hh | *.hpp )
echo "#include \"$f\"" > hcheck.cpp
printf "\n\033[4mChecking $f\033[0m\n"
make -s hcheck.o
rm -f hcheck.o hcheck.cpp
;;
esac
done
当然,你需要有一个Makefile
。如果您不想这样,则用make
适当的gcc
命令替换该行(不要忘记任何标志!)。如果您Makefile
将对象放在当前目录以外的位置,您还需要对其进行调整。
我敢肯定,还有很多需要改进的地方。当我告诉人们这件事时,下意识的反应是“编译头文件是一个愚蠢的想法”,但它对我来说效果很好,可以用于没有源代码或源代码中没有首先包含的头文件。
减轻实现自给自足标头目标的负担的一种方法是确保在那里声明的任何类(通常)或自由函数(有时)都有非常具体的意图,如坚持单一责任原则。通过这样做,需要包含标头的依赖项将会减少。
我不知道有这样的工具。这个问题并不像看起来那么容易解决。例如,以下应包含哪些头文件才能自给自足?
#ifdef FOO
std::vector<int> getVector();
#endif
void doStuff(std::string);
它可能需要也可能不需要包括<vector>
. 这取决于是否FOO
已定义,并且可能已定义或未定义,具体取决于此文件之前包含的内容。
通常,预处理器宏确实会干扰任何“孤立”读取标头的尝试。