Ваш компілятор щойно спробував скомпілювати названий файл foo.cc
. Після натискання номера рядка line
компілятор знаходить:
#include "bar"
або
#include <bar>
Потім компілятор намагається знайти цей файл. Для цього він використовує набір каталогів для пошуку, але в цьому наборі немає файлу bar
. Пояснення різниці між версіями твердження include див. Тут . .
Як сказати компілятору, де його знайти
g++
має опцію -I
. Це дозволяє додавати шляхи пошуку включити до командного рядка. Уявіть, що ваш файл bar
знаходиться у папці з іменем frobnicate
щодо foo.cc
(припустимо, ви компілюєте з каталогу, де foo.cc
знаходиться):
g++ -Ifrobnicate foo.cc
Ви можете додати більше шляхів включення; кожне, яке ви даєте, відносно поточного каталогу. Компілятор Microsoft має відповідний параметр/I
який працює так само, або у Visual Studio папки можна встановити на Сторінках властивостей проекту в розділі Властивості конфігурації-> C / C ++ -> Загальні-> Додаткові каталоги включення.
А тепер уявіть, що у вас є кілька версій bar
у різних папках, враховуючи:
#include<string>
std::string which() { return "A/bar"; }
#include<string>
std::string which() { return "B/bar"; }
#include<string>
std::string which() { return "C/bar"; }
#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
який постачається з вашою платформою C ++ як частина стандартної бібліотеки.
Це все дещо спрощено, але повинно дати вам основну ідею.
Подробиці про <>
/ ""
-пріоритети та-I
Відповідно до документації gcc , пріоритет для include <>
"нормальної системи Unix" такий:
/usr/local/include
libdir/gcc/target/version/include
/usr/target/include
/usr/include
Для програм на C ++ він також спочатку буде виглядати у / usr / include / c ++ / version. У наведеному вище ціль - це канонічна назва системи GCC, налаштованої на компіляцію коду для; [...].
У документації також зазначено:
Ви можете додати до цього списку за допомогою опції командного рядка -Idir. Всі каталоги з іменем -I шукаються в порядку зліва направо перед каталогами за замовчуванням . Єдиним винятком є випадки, коли каталог за замовчуванням вже шукається. У цьому випадку параметр ігнорується, а порядок пошуку системних каталогів залишається незмінним.
Щоб продовжити наш #include<list> / #include"list"
приклад (той самий код):
g++ -I. main.cc
і
#include<list>
int main () { std::list<int> l; }
і справді, -I.
пріоритети папки .
над системою включають, і ми отримуємо помилку компілятора.