使用C++头文件的最佳实践

Nav*_*K N 20 c++ header-files

我对头文件的使用有以下疑问.

1 - 在评论后加入警卫

/* Copyright Note and licence information (multiple lines) */
#ifndef FOO_H
#define FOO_H
// Header file contents
#endif
Run Code Online (Sandbox Code Playgroud)

Herb Sutter在他的"C++编码标准"一书中说,像上面这样的代码是有问题的.他说"#ifndef"语句应该出现在头文件的第一行.我觉得这并不令人信服.在头文件中你跟着你们/ gals吗?

2 - 在头文件中使用名称空间

#ifndef FOO_H
#define FOO_H
namespace FooNameSpace{
    // Header file contents
}
#endif
Run Code Online (Sandbox Code Playgroud)

上面的代码是否使用了正确的做法?我的意思是,你在头文件中使用命名空间吗?我知道为什么在头文件中导入命名空间是没有意义的,但是如上所述的声明呢?

如果上面的方法是正确的,那么如何对另一个名称空间中的类进行" 转发声明 "呢?是不是

#ifndef FOO_H
#define FOO_H
namespace AnotherNameSpace{
    class AnotherFoo; // forward declaration
}

namespace FooNameSpace{
    // Use AnotherFoo here
}
#endif
Run Code Online (Sandbox Code Playgroud)

" 前向声明 "是避免" 循环依赖 " 的唯一方法,对吗?

Ada*_*eld 18

  1. 包含警卫和评论的顺序纯粹是一种风格问题 - 它不会对编译速度产生任何可衡量的影响.

  2. 命名空间绝对应该在头文件中用于声明函数,类,全局变量,等等.你应该有什么不能做的是使用using的语句在头文件-这是不可能UNUSE在包括它的源文件的东西,你不应该强迫包含者在全局范围内添加额外的东西.如果您需要在标题中使用其他名称空间中的内容,请完全限定每个名称.它有时会很痛苦,但它确实是正确的做法.

例子:

// WRONG!
using namespace std;
class MyClass
{
    string stringVar;
};

// RIGHT
class MyClass
{
    std::string stringVar;
};
Run Code Online (Sandbox Code Playgroud)

至于其他命名空间中的类的前向声明,你已经完全正确了.只记得总是有资格AnotherFooAnotherNameSpace::AnotherFoo,当你引用它的水箱内.实际上,前向声明是打破循环依赖的唯一方法.


Mic*_*urr 7

  1. 我听说在包含守卫之前发表评论会导致一些编译器错过优化.如果防护是第一件事,编译器可能会识别成语,甚至不打算打开后续包含的标题.在我自己的代码中,注释通常在include guard之前.我从来没有打扰过测试,看看这是否有任何影响.我可能永远不会(但如果其他人这样做,我会对结果感兴趣).

  2. 当然,标题应该包含名称空间 - 否则在名称空间中没有任何用处.但是,正如您所提到的,标题不应该"导入"(因为缺少更好的单词)名称空间到带有' using'指令的编译单元中.