Избегайте зависимостей от неявно включённых имён
Причина
Избегайте неожиданностей. Избегайте необходимости изменять директивы #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"
Это правило против неявного включения не направлено против таких намеренных агрегаций.
Контроль
Для контроля потребуются некоторые знания о том, что в заголовке предназначено для «экспорта» пользователям, а что служит для обеспечения реализации. До появления модулей полноценное решение невозможно.