12

在 Effective C++(第 3 版)中,Scott Meyers 在第 31 条中建议类应该在其经典的声明 (.h) 和定义 (.cpp) 文件之上具有前向声明包含文件 (fwd.h),不需要完整定义的类可以使用,而不是前向声明自己。

我有点看到它的情况,但我真的不认为这是一个可行的选择......它似乎很难维护,相当矫枉过正而且几乎没有必要。

但是,我可以看到它用于模板前向声明,这是相当繁重的。但是对于简单的课程?似乎维护起来很痛苦,并且会创建大量几乎为空的包含文件,这些文件的用途非常小……值得麻烦吗?

这是一个例子:

// Class.h
class Class
{
    Class();
    ~Class();
};

// ClassFwd.h
class Class;

// Class.cpp
Class::Class()
{
}

Class::~Class()
{
}

我的问题

你们有什么感想?如果这是一个好习惯?

注意我最感兴趣的是这种做法的论点,看看我是否遗漏了一些能让我同意 Scott Meyers 的东西。

4

4 回答 4

7

我对所有库都使用了前向声明头文件。库通常具有以下结构:

lib/
  include/
    class headers + Fwd.h
src/
  source files + internal headers

lib/include目录将包含所有公共类标头以及一个前向声明标头。这使得库在包含方面变得轻量级。此库之外的任何标头仅包含前向标头 ( Fwd.h),而此库之外的源包含必要的完整标头。还可以提供一个方便的标头 ( Lib.h),其中包含所有其他标头,以在源文件中使用。

在前向声明头中放置的另一件事是typedefs for shared_ptr,尤其是在具有返回实现指针的工厂类的继承层次结构的情况下。

以上对于具有大量内部库的大型应用程序很有用。对于这种情况,对上述内容的改进是将公共标头放在lib/include/lib. 这样,您图书馆的客户就必须包括lib/.... 将其视为标题的命名空间。

祝你好运!

于 2010-10-14T16:38:59.150 回答
2

将一个简单class Whatever;的放在它自己的标题中没有任何优点和很多缺点。

尤其是在访问标头可能很耗时的情况下,可以使用简单的前向声明来避免访问标头;将它们放在自己的标题中会破坏目的......

正如您所注意到的,对于模板化的东西,这是另一回事。例如,<iosfwd>从标准库中签出。

干杯&hth。

于 2010-10-14T16:11:59.007 回答
1

这种做法使代码用户不必考虑类是常规类还是模板类。用户只需#inludes“corresponding_fwd.h”文件并具有类引用。对用户来说少一点烦恼是一件好事。但是,如果它是一个小项目或类的创建者是唯一的类用户,那么它可能会更烦人。所以,这取决于。

于 2010-10-14T16:15:24.677 回答
0

如果您有一个大型解决方案,这是您处理固有依赖项的唯一机会:

struct A {
    B* m_pB;
};

struct B {
    A* m_pA;
};

现在 A 和 B 可能合理地位于不同的头文件中,甚至可能位于不同的项目中。然而,它们的依赖并不是某种设计缺陷,而是完全合乎逻辑和必要的。你做什么工作?

  1. 首先为每个需要的项目包含一个单独的 Types.h 前向声明头,即,前向声明没有每个类自己的头文件。
  2. 然后包括所有必需项目的 Class.h。这些标头将需要前向声明才能编译。
  3. 包括主项目的标题。

在一个相当大的解决方案(500k LOC)中,我发现这种模式非常容易管理。否则,如果您更改一个类声明,您在哪里可以找到您可能在任意数量的其他头文件中单独进行的所有前向声明?

于 2010-10-14T16:09:06.270 回答