19 November 2023

C++ 核心指南目录

“Avoid dependencies on implicitly #include d names”

理由

避免惊讶。避免因为一个包含的头文件改动了,不得不修改 #include 列表。避免因为头文件,造成逻辑上独立的实现细节之家互相依赖。

坏例子

#include <iostream>
using namespace std;

void use()
{
    string s;
    cin >> s;               // fine
    getline(cin, s);        // error: getline() not defined
    if (s == "surprise") {  // error == not defined
        // ...
    }
}

<iostream> 会暴露 std::string 的定义(为何?)。但是不会包含整个 <string> 头文件。于是会引起一些初学者的问题:为何 getline(cin, s); 无法工作?为什么 string 无法通过 == 进行比较判断?

解决方案是显式的添加 #include <string>;

好例子

#include <iostream>
#include <string>
using namespace std;

void use()
{
    string s;
    cin >> s;               // fine
    getline(cin, s);        // fine
    if (s == "surprise") {  // fine
        // ...
    }
}

注意

有些头文件就是用来收集多个不同头文件的,比如:

// basic_std_lib.h:

#include <string>
#include <map>
#include <iostream>
#include <random>
#include <vector>

用户可以通过单个 #include 就把以上头文件都包含进来了。

#include "basic_std_lib.h"

此条规则反对隐式包含,但是并不阻止这种有意的头文件聚合设计。

强化

强化手段需要知道头文件里哪些是导出的,哪些是实现细节相关的。在我们有 C++ module 之前,暂时没有什么好的解决方案。