typedef的头文件最佳实践

Rob*_*ier 51 c++ typedef

我在一个项目中广泛使用了shared_ptr和STL,这导致了过长的,容易出错的类型shared_ptr< vector< shared_ptr<const Foo> > >(我喜欢ObjC程序员,长名称是常态,但这仍然太过分了.)我相信,更加清楚的是,一致地调用它FooListPtr并记录命名约定,"Ptr"表示shared_ptr,"List"表示shared_ptr的向量.

这很容易输入typedef,但它会导致头文件出现问题.我似乎有几个选项可以定义FooListPtr:

  • Foo.h. 这会缠绕所有标题并造成严重的构建问题,因此它不是首发.
  • FooFwd.h("前向标题").这就是Effective C++建议的,基于iosfwd.h.它非常一致,但保持两倍标题的开销似乎很烦人.
  • Common.h(将所有这些放在一个文件中).这通过缠绕许多不相关的类型来杀死可重用性.您现在不能只拿起一个对象并将其移动到另一个项目.这不是首发.
  • 某种类似幻想的#define魔法,如果它还没有被typedefed,那就是typedef.我对预处理器持续不喜欢,因为我认为它让新人很难理解代码,但也许......
  • 使用向量子类而不是typedef.这似乎很危险......

这里有最好的做法吗?当可重用性,可读性和一致性至关重要时,它们如何在实际代码中生效?

如果其他人想要添加其他选项供讨论,我已经标记了这个社区维基.

Ash*_*ain 14

我正在编写一个听起来像是使用该common.h方法的项目.它对该项目非常有效.

有一个文件被调用ForwardsDecl.h,它位于预编译的头文件中,只是向前声明所有重要的类和必要的typedef.在这种情况下unique_ptr使用而不是shared_ptr,但用法应该类似.它看起来像这样:

// Forward declarations
class ObjectA;
class ObjectB;
class ObjectC;

// List typedefs
typedef std::vector<std::unique_ptr<ObjectA>> ObjectAList;
typedef std::vector<std::unique_ptr<ObjectB>> ObjectBList;
typedef std::vector<std::unique_ptr<ObjectC>> ObjectCList;
Run Code Online (Sandbox Code Playgroud)

Visual C++ 2010接受此代码,即使这些类仅是前向声明的(完整的类定义不是必需的,因此不需要包含每个类的头文件).我不知道那个标准和其他编译器是否需要完整的类定义,但它不是很有用:另一个类(ObjectD)可以将ObjectAList作为成员,而不需要包含ObjectA.h - 这可以真的有助于减少头文件依赖!

维护不是特别的问题,因为转发声明只需要写一次,任何后续更改只需要在类的头文件中的完整声明中发生(这将触发更少的源文件由于减少而重新编译依赖).

最后看起来这可以在项目之间共享(我没有尝试过自己),因为即使一个项目实际上没有声明一个ObjectA,它也没关系,因为它只是前向声明的,如果你不使用它编译器不在乎.因此,该文件可以包含其所使用的所有项目中的类的名称,并且如果特定项目缺少某些项,则无关紧要.所需要的只是必要的完整声明标头(例如ObjectA.h)包含在实际使用它们的任何源(.cpp)文件中.


Kon*_*lph 6

我会采用前向标题和一种common.h特定于您的项目的标题的组合方法,并且只包括所有前向声明标题和任何其他常见且轻量级的内容.

你抱怨保持两次标题数量的开销,但我不认为这应该是一个太大的问题:转发标题通常只需要知道非常有限数量的类型(一个?),有时甚至不知道完整的类型.

你甚至可以尝试使用脚本自动生成头文件(这在SeqAn中完成),如果真的那么多头文件.