.h 还是 .hpp 用于 C++ 头文件?一劳永逸地搞清楚
如果你用 C++ 编程超过几周,很可能遇到过这个问题。打开别人的项目——里面是 .h。自己开始一个新项目——脑子里有个声音:“也许 .hpp 更酷?” 或者反过来:你是 .h 的狂热粉丝,而同事坚持认为 .hpp 才是唯一正确的选择。
剧透:两种扩展名在技术上都是正确的。编译器并不关心。但区别确实存在,并且对于代码组织、可读性和项目维护很重要。让我们来深入探讨这两种扩展名背后的含义,以及何时选择哪一种。
简短回答:根本区别是什么?
简而言之:
.h—— 传统的头文件扩展名,源自 C 语言。在 C 和 C++ 中均可使用。.hpp—— 更现代的扩展名,明确表示:“这是 C++,不是 C”。其设计初衷是为了区分 C++ 头文件和 C 头文件。
但细节决定成败。让我们深入探究。
历史背景:.h 和 .hpp 从何而来?
C 语言从远古时代就开始使用 .h 作为头文件扩展名。当 C++ 出现时,起初程序员们只是继续使用 .h —— 这完全没问题。C++ 标准库(例如 <iostream>)甚至完全放弃了扩展名,但那是另一个故事了。
.hpp 扩展名的出现是为了满足区分 C 和 C++ 代码的需求。想象一下:你有一个大型项目,其中部分文件是 C 语言,部分是 C++。你可能用不同的编译器或不同的编译选项来构建它。如何快速判断某个头文件对应哪种语言?没错——看扩展名。
因此,.hpp(源自“C Plus Plus header”)在社区中成为了纯 C++ 头文件的事实标准,尤其是在像 Boost 这样的库中。
何时使用 .h?
先别急着抛弃 .h。它有自己的优势:
- 与 C 的兼容性。 如果你的头文件需要同时被 C 和 C++ 代码引用——只能用
.h。别无选择。 - 保守的项目。 在大型代码库中,代码风格已经形成多年,将扩展名改为
.hpp只会徒增麻烦。 - 简洁性。 三个字符比四个字符少。小事一桩,但令人愉悦。
示例:兼容 C 和 C++ 的头文件
// math_utils.h#ifndef MATH_UTILS_H#define MATH_UTILS_H
#ifdef __cplusplusextern "C" {#endif
int add(int a, int b);int multiply(int a, int b);
#ifdef __cplusplus}#endif
#endif // MATH_UTILS_H这样的文件既可以包含在 .c 文件中,也可以包含在 .cpp 文件中。如果你把它命名为 math_utils.hpp,C 程序员可能会困惑:“这真的是给我的吗?”
何时使用 .hpp?
这里正好相反:.hpp 是现代 C++ 程序员的选择。尤其是当:
- 你只编写 C++ 代码。 项目中完全没有 C 语言,将来也不会有。
- 你使用模板、STL、异常。 这些都是纯 C++ 的特性,
.hpp扩展名可以强调这一点。 - 你想明确区分 C++ 代码和 C 代码。 在混合项目中,这可以避免混淆。
- 你遵循现代实践。 Boost、Qt(部分)、许多新库都使用
.hpp。
示例:典型的包含类的 C++ 头文件
// player.hpp#ifndef PLAYER_HPP#define PLAYER_HPP
#include <string>#include <vector>
class Player {public: Player(const std::string& nam