Нет файлов заголовков, включенных в файл, но все еще может использовать классы / функции из не включенных файлов заголовков

#c #include #translation-unit

#c #включить #translation-unit

Вопрос:

Вот некоторый код из рассматриваемого файла, называемый Global.h, который используется в других заголовочных файлах и, похоже, отлично компилируется:

 #pragma once

enum SType {null, lab, assignment, testPrep};
enum Code {none, 123, 222, 333, 432};

template<typename D>
bool validate(D task = string, D date = string) {

    bool result = true;

    if (task.size() < 3) {
        cout << "Task too simple, please elaborate." << endl;
        result = false;
    }
    else if (task.size() > 50) {
        cout << "Task too detailed. Only 30 chars allowed." << endl;
        task.empty();
        result = false;
    }

if (date == "02/20/93") {
    date.empty();
    date = "My birthday!";
}

    return resu<

}
 

Как вы можете видеть, я могу использовать объекты string и ostream без объявления использования пространства имен или конкретного файла. Очевидно, это означает, что Global.h извлекает информацию откуда-то еще, но мне любопытно, откуда поступает эта информация? Я всегда думал, что заголовочный файл будет реконструировать код из других файлов, только если они были включены с директивой #include в сам файл, поэтому я не уверен, как это происходит, и мне любопытно узнать, что происходит.

Комментарии:

1. вы имеете в виду, что вы компилируете его, используя g -c Global.h , и он работает?

2. @Жан-Франсуа Фабр Это работает в Visual Studio, не уверен, что с этим будет делать компилятор gcc

Ответ №1:

Нет. Просто все, что включает этот Global.h заголовочный файл, должно быть, уже #include содержит все необходимые заголовки.

Некоторое упрощение: #include оператор заменяется логической вставкой содержимого общего #include файла вместо самого #include оператора. При компиляции модуля перевода все #include инструкции обрабатываются таким образом. Как будто все #include операторы логически заменяются содержимым файла, на который ссылается. Конечным результатом является один логический исходный файл, единица перевода, который компилируется от начала до конца.

Итак, если после обработки всех #include инструкций таким образом, до тех пор, пока необходимые файлы заголовков, <iostream> , и другие логически вставляются в логическую единицу перевода до <iostream> того, как из этого файла заголовка будут ссылаться на классы и другие ресурсы, эта единица перевода будет скомпилирована без проблем. Является ли это тем же заголовочным файлом, который #include содержит требуемые заголовочные файлы, <iostream> и другими; или какой-либо другой заголовочный файл, который #include был добавлен ранее, который #include содержит эти заголовочные файлы; это не имеет значения.

Это правда, что хорошая практика указывает, что для каждого файла должны быть явно #include указаны его предварительные условия. Но если этого не произойдет, пока какой-либо другой заголовочный файл уже #include был разделен, модуль перевода все равно будет компилироваться.