在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的内容。
答案 0 :(得分:6)
我为所有库使用了前向声明头文件。库通常具有以下结构:
lib/
include/
class headers + Fwd.h
src/
source files + internal headers
lib/include
目录将包含所有公共类标题以及一个前向声明标头。这使得图书馆在包含方面轻量化。此库外的任何标头仅包含转发标头(Fwd.h
),而此库外的源包括必要的完整标头。还可以提供包含所有其他标头的便捷标头(Lib.h
),以便在源文件中使用。
前向声明标头中的另一个内容是typedef
,shared_ptr
,特别是在具有返回实现指针的工厂类的继承层次结构的情况下。
以上内容对于具有大量内部库的大型应用程序非常有用。对于这种情况,上述内容的改进将是将公共标题放在lib/include/lib
中。这样,您图书馆的客户必须包含lib/...
。可以将其视为标题的命名空间。
答案 1 :(得分:2)
在自己的标题中放置一个简单的class Whatever;
没有任何优点和许多缺点。
特别是在访问标头可能非常耗时的情况下,使用简单的前向声明来避免访问标头;将它们放在自己的标题中会使目的失败......
正如你所注意到的那样,模板化的东西是另一回事。例如。从标准库中查看<iosfwd>
。
干杯&amp;第h
答案 2 :(得分:1)
这种做法允许代码用户不要考虑一个类是常规的还是模板的。用户只需#inludes“associated_fwd.h”文件并具有类引用。对用户来说,一点烦恼就是A Good Thing。但如果它是一个小项目或类'创建者是唯一的类'用户那么它可能会更烦恼。所以,这取决于。
答案 3 :(得分:0)
如果您有一个大型解决方案,这是您处理固有依赖关系的唯一机会:
struct A {
B* m_pB;
};
struct B {
A* m_pA;
};
现在A和B可能合理地位于不同的头文件中,甚至可能是不同的项目。然而,他们的依赖不是一些设计缺陷,而是完全合乎逻辑且必要的。你是做什么?
在一个相当大的解决方案(500k LOC)中,我发现这种模式非常容易管理。否则,如果您更改了类声明,那么在哪里可以找到您在任意数量的其他头文件中单独生成的所有前向声明?