我有一个关于包含头文件时的“最佳实践”的问题。
显然,include保护可以防止我们在一个头文件或源文件中包含多个include,所以我的问题是,你是否发现在一个头文件或源文件中包含所有需要的头文件是有益的,即使其中一个头文件已经包含了另一个include。这样做的理由是,读者可以看到文件所需的所有内容,而不是在其他头文件中寻找。
例如:假设使用了include guards:
// Header titled foo.h
#include "blah.h"
//....。
// Header titled bar.h that needs blah.h and foo.h
#include "foo.h"
#include "blah.h" // Unnecessary, but tells reader that bar needs blah另外,如果头文件中不需要头文件,但它的相关源文件中需要头文件,那么是将其放在头文件中还是放在源文件中?
发布于 2009-10-28 09:09:07
基本规则是,对代码中实际使用的任何头文件执行#include操作。所以,如果我们说的是:
// foo.h
#include "utilities.h"
using util::foobar;
void func() {
foobar();
}
// bar.h
#include "foo.h"
#include "utilities.h"
using util::florg;
int main() {
florg();
func();
}如果bar.h使用了两次包含的头中的工具,那么您应该对其执行#include操作,即使您不一定要这样做。另一方面,如果bar.h不需要来自utilities.h的任何函数,那么即使foo.h包含它,也不要#include它。
发布于 2009-10-28 09:45:32
源文件的头文件应该定义代码的用户需要正确使用它的接口。它应该包含他们使用该接口所需的所有内容,但没有额外的内容。如果他们需要xyz.cpp提供的功能,那么用户所需要的就是#include "xyz.h"。
“xyz.h”如何提供该功能在很大程度上取决于“xyz.h”的实现者。如果它需要只能通过包含特定标头来指定的工具,那么“xyz.h”应该包含另一个标头。如果它可以避免包含特定的报头(通过转发定义或任何其他干净的方式),它应该这样做。
在本例中,我的编码可能取决于“foo.h”头文件是否与“blah.h”头文件处于同一项目的控制之下。如果是这样,那么我可能不会显式地包含第二个include;如果不是这样,我可能会包含它。然而,上面的声明应该迫使我说“是的,为了以防万一,包括'foo.h‘”。
在我的辩护中,我认为C++标准允许包含任何一个C++标头来包含其他标头-如实现所需;这可以被视为类似。问题是,如果您只包含'bar.h‘,但仍使用'blah.h’中的功能,那么当'bar.h‘因为其代码不再需要'blah.h’而被修改时,用户过去(意外地)编译的代码现在会失败。
但是,如果用户直接访问'blah.h‘工具,那么用户应该直接包含'blah.h’。修改后的'bar.h‘中的代码接口不再需要'blah.h’,所以任何只使用'bar.h‘的接口的代码应该仍然可以。但如果代码也使用了'blah.h‘,那么它就应该直接包含它。
我怀疑德米特定律也应该被考虑-或者可以被视为影响这一点。基本上,“bar.h”应该包括使其工作所需的头部,无论是直接的还是间接的-并且“bar.h”的消费者不应该太担心它。
回答最后一个问题:显然,实现需要但接口不需要的头部应该只包含在实现源代码中,而绝对不应该包含在头部中。实现所使用的与用户无关,编译效率和信息隐藏都要求报头只向报头的用户公开最少的必要信息。
发布于 2009-10-28 08:13:47
在C++的头文件中预先包含所有内容可能会导致编译时间激增
最好是尽可能多地封装和转发声明。转发声明为使用该类所需的内容提供了足够的提示。不过,在其中包含标准内容是可以接受的(尤其是模板,因为它们不能被向前声明)。
https://stackoverflow.com/questions/1634443
复制相似问题