Должен ли я включать заголовок, который уже включен через другие заголовки?

Я только что заметил, что мои программы, использующие класс string, компилировались без включения заголовка <string>. Оказывается, что <iostream> включает <ios_base>, который, в свою очередь, включает <string>.

Является ли эта плохая практика и я должен явно включать <string>? Даже если это всего лишь случай ясности?

Можно ли предположить, что это относится не только к заголовку <string>? Возможно, это специфичная реализация, и стандартное состояние включает заголовок <string> через <ios_base> и <iostream>? Обеспечение того, чтобы любая уважаемая и широко используемая реализация всегда включала <string>, обеспечивающую вызов <iostream>.

Ответ 1

Вы должны явно включать любые стандартные заголовки библиотек, которые вам нужны.

Не указано, какие стандартные заголовки библиотек включены в другие стандартные заголовки библиотек, поэтому такие детали будут отличаться между компиляторами.

Один случай, когда вы можете положиться на заголовок, который будет включен другим заголовком, - это если класс в одном заголовке происходит из класса в другом. Например, <iostream> должен включать <ios_base>, потому что классы, определенные в <iostream>, производятся из классов, определенных в <ios_base>.

Ответ 2

Хорошей практикой является всегда включать заголовки для классов, которые вы будете использовать в заданном исходном файле, независимо от того, знаете ли вы, что они включены в уже включенные файлы.

Если при рефакторинге вашего кода вы удаляете необходимость в одном из файлов с более высоким уровнем (например, iostream), может возникнуть довольно болезненно определить, почему ваше приложение больше не компилируется.

Ответ 3

Если вы добавляете правильный заголовок (с "#pragma once" или правильным #ifndef) более одного раза, он добавляет немного времени на компиляцию (просто для открытия, анализа и удаления содержимого содержимого заголовка), но ничего слишком серьезного, в то время как он делает ваши файлы более легкими для компиляции, если обстоятельства меняются (т.е. переместить их в другой проект, сделать из них библиотеку и т.д.), Если вы действительно обеспокоены временем компиляции, добавьте тот же #ifndef перед включением заголовка (хотя я не рекомендую его)

то есть.

// header.h
#ifndef _HEADER_H
#define _HEADER_H
int blahblahblah(int);
#endif


// cppfile.cpp
#ifndef _HEADER_H
#include <header.h>
#endif