Должен ли я включать заголовок, который уже включен через другие заголовки?
Я только что заметил, что мои программы, использующие класс 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