我的类定义一直使用*.h文件,但在阅读了一些boost库代码后,我意识到它们都使用*.hpp。我一直很讨厌这个文件扩展名,我想主要是因为我不习惯它。

使用*.hpp而不是*.h的优点和缺点是什么?


当前回答

工具和人类很容易区分事物。就是这样。

在常规使用中(通过boost等),.hpp是特别的c++头文件。另一方面,.h用于非c++专用的头文件(主要是C)。由于存在许多非平凡的情况,因此精确检测内容的语言通常很难,因此这种差异通常使现成的工具易于编写。对于人类来说,一旦习惯了,也就容易记忆和使用了。

然而,我要指出,公约本身并不总是如预期的那样有效。

它不受语言规范的强迫,无论是C还是c++。有许多项目不遵循惯例。一旦你需要合并(混合)它们,就会很麻烦。 .hpp本身不是唯一的选择。为什么不是。hh或。hxx?(尽管无论如何,您通常至少需要一个关于文件名和路径的常规规则。)

我个人在我的c++项目中使用。h和。hpp。我没有遵循上面的惯例,因为:

The languages used by each part of the projects are explicitly documented. No chance to mix C and C++ in same module (directory). Every 3rdparty library is required to conforming to this rule. The conformed language specifications and allowed language dialects used by the projects are also documented. (In fact, I even document the source of the standard features and bug fix (on the language standard) being used.) This is somewhat more important than distinguishing the used languages since it is too error-prone and the cost of test (e.g. compiler compatibility) may be significant (complicated and time-consuming), especially in a project which is already in almost pure C++. Filenames are too weak to handle this. Even for the same C++ dialect, there may be more important properties suitable to the difference. For example, see the convention below. Filenames are essentially pieces of fragile metadata. The violation of convention is not so easy to detect. To be stable dealing the content, a tool should eventually not only depend on names. The difference between extensions is only a hint. Tools using it should also not be expected behave same all the time, e.g. language-detecting of .h files on github.com. (There may be something in comments like shebang for these source files to be better metadata, but it is even not conventional like filenames, so also not reliable in general.)

我通常在c++的头文件中使用.hpp,并且头文件应该只以头文件的方式使用(维护),例如作为模板库。对于.h中的其他头文件,要么有相应的.cpp文件作为实现,要么是非c++头文件。后者对于人工(或具有显式嵌入元数据的工具,如果需要的话)通过头的内容进行区分是微不足道的。

其他回答

There is no advantage to any particular extension, other than that one may have a different meaning to you, the compiler, and/or your tools. header.h is a valid header. header.hpp is a valid header. header.hh is a valid header. header.hx is a valid header. h.header is a valid header. this.is.not.a.valid.header is a valid header in denial. ihjkflajfajfklaf is a valid header. As long as the name can be parsed properly by the compiler, and the file system supports it, it's a valid header, and the only advantage to its extension is what one reads into it.

话虽如此,能够基于扩展准确地做出假设是非常有用的,因此对于头文件使用一组易于理解的规则将是明智的。就我个人而言,我更喜欢这样做:

If there are already any established guidelines, follow them to prevent confusion. If all source files in the project are for the same language, use .h. There's no ambiguity. If some headers are compatible with multiple languages, while others are only compatible with a single language, extensions are based on the most restrictive language that a header is compatible with. A header compatible with C, or with both C & C++, gets .h, while a header compatible with C++ but not C gets .hpp or .hh or something of the sort.

This, of course, is but one of many ways to handle extensions, and you can't necessarily trust your first impression even if things seem straightforward. For example, I've seen mention of using .h for normal headers, and .tpp for headers that only contain definitions for templated class member functions, with .h files that define templated classes including the .tpp files that define their member functions (instead of the .h header directly containing both the function declaration and the definition). For another example, a good many people always reflect the header's language in its extension, even when there's no chance of ambiguity; to them, .h is always a C header and .hpp (or .hh, or .hxx, etc.) is always a C++ header. And yet again, some people use .h for "header associated with a source file" and .hpp for "header with all functions defined inline".

考虑到这一点,主要的优势在于始终以相同的风格命名你的头文件,并使这种风格对任何检查你的代码的人来说都很明显。这样,任何熟悉您通常的编码风格的人都可以粗略地看一下,就可以确定您对任何给定扩展的意思。

在Bjarne Stroustrup的《c++程序设计语言第三版》(第nº1本c++必读书籍)中,他使用了*.h。所以我认为最好的做法是使用*.h。

但是,*.hpp也很好!

我使用.hpp是因为我想让用户区分哪些头文件是c++头文件,哪些头文件是C头文件。

当你的项目同时使用C和c++模块时,这一点非常重要:就像其他人在我之前解释的那样,你应该非常小心地做这件事,它从你通过扩展提供的“契约”开始

.hpp: c++头文件

(或。hxx,或。hh,或其他)

此头文件仅适用于c++。

如果你在C模块,甚至不要尝试包含它。你不会喜欢它,因为没有努力使它对c友好(太多的东西会丢失,比如函数重载、名称空间等等)。

.h:兼容C/ c++或纯C头文件

C源代码和c++源代码都可以直接或间接地包含这个头文件。

它可以直接包含,由__cplusplus宏保护:

这意味着,从c++的观点来看,与C兼容的代码将被定义为extern“C”。 从C的角度来看,所有的C代码都是清晰可见的,但c++代码是隐藏的(因为它不会在C编译器中编译)。

例如:

#ifndef MY_HEADER_H
#define MY_HEADER_H

   #ifdef __cplusplus
      extern "C"
      {
   #endif

   void myCFunction() ;

   #ifdef __cplusplus
      } // extern "C"
   #endif

#endif // MY_HEADER_H

或者它可以通过相应的.hpp头以extern“C”声明间接包含。

例如:

#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP

extern "C"
{
#include "my_header.h"
}

#endif // MY_HEADER_HPP

and:

#ifndef MY_HEADER_H
#define MY_HEADER_H

void myCFunction() ;

#endif // MY_HEADER_H

我一直认为.hpp头文件是.h和.cpp文件的混合…还包含实现细节的标头。

通常,当我看到(并使用).hpp作为扩展名时,没有相应的.cpp文件。正如其他人所说,这不是一个严格的规则,只是我倾向于使用.hpp文件。

使用哪个扩展名并不重要。两种都可以。

我用*.h表示C,用*.hpp表示c++。