Как уже говорили другие, более безопасно напрямую включать файлы, которые вы используете, с точки зрения защиты от будущих изменений в файле, на который вы полагаетесь при пересылке.
Это также обычно считаетсячище, чтобы ваши зависимости сразу там.Если вы хотите проверить, что это за объект "MyClass", просто прокрутите вверх и попросите свою среду разработки перенести вас в соответствующий заголовок.
Стоит отметить, что безопасно включать один и тот же стандартный заголовок несколько раз, как это предусмотрено стандартной гарантией библиотеки.На практике это означает, что реализация ( в, скажем, libc ++ clang) начнется с #include
guard.Современные компиляторы настолько знакомы с идиомой включения защиты (особенно в применении их собственных реализаций стандартной библиотеки), что могут даже не загружать файлы.Таким образом, единственное, что вы теряете в обмен на эту безопасность и ясность, - это набирать дополнительные дюжины или около того букв.
Все это было согласовано со всеми, я перечитал его, и я не думаю, что на самом деле ваш вопрос был "Должен ли я это сделать?"столько, сколько "Почему мне даже разрешено не делать этого?"Или «Почему компилятор не изолирует меня от включенных включений?»
Есть одно важное исключение из правила "непосредственно включайте то, что вы используете".Это заголовки, которые, как часть их спецификации , включают дополнительные заголовки.Например, <<a href="https://en.cppreference.com/w/cpp/header/iostream" rel="nofollow noreferrer">iostream
> (который, конечно, сам является частью стандартной библиотеки), начиная с c ++ 11, гарантированно включает <istream>
и <ostream>
.Кто-то может сказать: «Почему бы просто не перенести содержимое <istream>
и <ostream>
в <iostream>
напрямую?»но есть и ясность и преимущества в скорости компиляции, так как есть возможность разбить их, если нужен только один.(И, без сомнения, для c ++ есть и исторические причины). Конечно, вы можете сделать это и для своих собственных заголовков.(Это больше похоже на Objective-C, но они имеют одинаковую механику включения и традиционно используют их для зонтичных заголовков, единственной задачей которых является включение других файлов.)
Есть еще одна фундаментальная причина, по которой заголовки включаютсявключай, включай.То есть, как правило, ваши заголовки не имеют смысла без них.Предположим, что ваш файл MyClass.hpp
содержит следующий синоним типа
using NumberPack = std::vector<unsigned int>;
и следующую самоописательную функцию
NumberPack getFirstTenNumers();
Теперь предположим, что другой файл включает MyClass.hpp
и имеет следующий.
NumberPack counter = getFirstTenNumbers();
for (auto c : counter) {
std::cout << c << "\n"
}
Здесь происходит то, что вы можете не захотеть записывать в свой код, который вы используете <vector>
.Это деталь реализации, о которой вам не нужно беспокоиться.NumberPack
, насколько вам известно, может быть реализован как какой-то другой контейнер, итератор, или объект типа генератора, или что-то еще, при условии, что он следует его спецификации.Но компилятор должен знать, что это на самом деле: он не может эффективно использовать родительские зависимости, не зная, что такое заголовки дедушки и бабушки.Побочным эффектом этого является то, что вам не по вкусу их использование.
Или, конечно, третья причина - просто «Потому что это не C ++».Да, у кого-то мог быть язык, на котором не передавались зависимости второго поколения, или вы должны были явно запросить его.Просто это будет другой язык, и, в частности, не вписывается в старый текст, включающий в себя стиль c ++ или друзей.