Ответ 1
Ваш компилятор просто попытался скомпилировать файл с именем foo.cc
. При попадании номера строки line
компилятор обнаруживает:
#include "bar"
или
#include <bar>
Затем компилятор пытается найти этот файл. Для этого он использует набор каталогов для поиска, но в этом наборе нет файла bar
. Для объяснения различия между версиями оператора include смотрите здесь.
Как сообщить компилятору, где его найти
g++
имеет опцию -I
. Он позволяет добавлять пути поиска к командной строке. Представьте, что ваш файл bar
находится в папке с именем frobnicate
, относительно foo.cc
(предположим, что вы компилируете из каталога, где находится foo.cc
):
g++ -Ifrobnicate foo.cc
Вы можете добавить дополнительные include-paths; каждый, который вы даете, относится к текущему каталогу. Компилятор Microsoft имеет параметр корреляции /I
, который работает аналогичным образом или в Visual Studio, папки могут быть установлены на страницах свойств проекта, в разделе "Свойства конфигурации" → C/С++ → Общие → Дополнительные каталоги включения,
Теперь представьте, что у вас есть несколько версий bar
в разных папках, учитывая:
// A/bar
#include<string>
std::string which() { return "A/bar"; }
// B/bar
#include<string>
std::string which() { return "B/bar"; }
// C/bar
#include<string>
std::string which() { return "C/bar"; }
// foo.cc
#include "bar"
#include <iostream>
int main () {
std::cout << which() << std::endl;
}
Приоритет с #include "bar"
является самым левым:
$ g++ -IA -IB -IC foo.cc
$ ./a.out
A/bar
Как вы видите, когда компилятор начал просматривать A/
, B/
и C/
, он остановился при первом или крайнем ударе.
Это относится к обеим формам, include <>
и incude ""
.
Разница между #include <bar>
и #include "bar"
Обычно #include <xxx>
заставляет его сначала заглядывать в системные папки, #include "xxx"
заставляет его сначала просматривать текущие или пользовательские папки.
например:.
Представьте, что в папке проекта есть следующие файлы:
list
main.cc
с main.cc
:
#include "list"
....
Для этого ваш компилятор будет #include
файл list
в вашей папке проекта, потому что в настоящее время он компилирует main.cc
и этот файл list
находится в текущей папке.
Но с main.cc
:
#include <list>
....
а затем g++ main.cc
, ваш компилятор сначала рассмотрит системные папки, а поскольку <list>
является стандартным заголовком, он будет #include
файлом с именем list
, который поставляется с вашей платформой С++, как часть стандартная библиотека.
Все это немного упрощено, но должно дать вам основную идею.
Подробная информация о <>
/""
-priorities и -I
В соответствии с gcc-documentation приоритет для include <>
находится в "нормальной системе Unix" следующим образом:
/usr/local/include
libdir/gcc/target/version/include
/usr/target/include
/usr/include
Для программ на С++ он также будет выглядеть в/usr/include/С++/version. В приведенном выше примере цель - это каноническое имя системы, для которой GCC был настроен для компиляции кода; [...].
В документации также указано:
Вы можете добавить в этот список опцию командной строки -Idir. Все каталоги, названные -I, выполняются в порядке слева направо перед каталогами по умолчанию. Единственное исключение - когда dir уже выполняется по умолчанию. В этом случае опция игнорируется, и порядок поиска для системных каталогов остается неизменным.
Чтобы продолжить наш пример #include<list> / #include"list"
(тот же код):
g++ -I. main.cc
и
#include<list>
int main () { std::list<int> l; }
и действительно, -I.
имеет приоритет в папке .
по всей системе, и мы получаем ошибку компилятора.