#include - это всего лишь буквальное вырезание и вставка содержимого включаемого файла (с развернутыми макросами и вставленными маркерами файлов / строк, чтобы можно было проследить источник).
Когда вы включаете iostream , если он внутренне включает string , то вы включаете строку транзитивно.Это считается плохим, потому что нет гарантии, что заголовки стандартной библиотеки будут включать другие заголовки, поэтому ваш код не переносим и имеет небольшую зависимость от версии используемой вами стандартной библиотеки.
Если выдобавьте в ваш код включение для string , так как препроцессор защищает от повторяющихся включений заголовков, оно будет настолько тщательно подавлено, что никаких доказательств того, что это включение вообще не будет присутствовать в его выходных данных.Компилятору не с чем работать, и он не может надежно выдать предупреждение, которое вы хотели бы получить без ложных срабатываний.
Например: допустим, у нас есть файл .cpp с main и заголовок a.hpp:
Заголовок "a.hpp":
#pragma once
namespace A {
void a_function() { }
}
Заголовок "b.hpp"
#pragma once
#include "a.hpp"
namespace B {
void b_function() { }
}
и main.cpp теперь выглядят так:
#include "b.hpp" // only include b...
int main() { A::a_function(); } // ... but use something in a.hpp
Компилируется, но предупреждений нет.Предварительно обработанный вывод выглядит следующим образом:
# 1 "main.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.cpp"
# 1 "b.hpp" 1
# 1 "a.hpp" 1
namespace A {
void a_function() { }
}
# 3 "b.hpp" 2
namespace B {
void b_function() { }
}
# 2 "main.cpp" 2
int main() { }
Кажется разумным, и мы можем видеть, что a был включен B, и должен выдать ошибку, верно?
Давайте исправим это и попробуем снова:
#include "b.hpp"
#include "a.hpp"
int main() { }
Повторная предварительная обработка еще раз:
# 1 "main.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.cpp"
# 1 "b.hpp" 1
# 1 "a.hpp" 1
namespace A {
void a_function() { }
}
# 3 "b.hpp" 2
namespace B {
void b_function() { }
}
# 2 "main.cpp" 2
int main() { }
100% идентично предыдущему. Мы исправили проблему, но в предварительно обработанном выводе нет никаких указаний.
Если препроцессор не дал больше информации, никакие изменения в компиляторе не могли бы удовлетворить ваш запрос.