Які із заголовних файлів необхідно включити в програму на С щоб можна було відкрити файл для




Які із заголовних файлів необхідно включити в програму на С  щоб можна було відкрити файл для



Файли заголовків (C++)

Імена елементів програми, таких як змінні, функції, класи і т. д. повинні бути оголошені до їх використання. Наприклад, ви не можете просто написати x=42 без першого оголошення "x".

int x; //Declaration x = 42; // use x

Оголошення повідомляє компілятору, є int чи елемент , функцією double , або class іншою річчю. Крім того, кожне ім'я має бути оголошено (прямо чи опосередковано) у кожному .cpp файлі, в якому він використовується. У разі компіляції програми кожен .cpp-файл компілюється незалежно в одиницю компіляції. Компілятор не знає, які імена оголошуються у інших одиницях компіляції. Це означає, що якщо ви визначаєте клас або функцію або глобальну змінну, необхідно вказати оголошення цієї речі в кожному додатковому файлі .cpp, який використовує його. Кожне оголошення цієї речі має бути точно ідентичним у всіх файлах. Невелика невідповідність призведе до помилок або ненавмисної поведінки, коли компонувальник намагається об'єднати всі одиниці компіляції в одну програму.

Щоб мінімізувати потенціал помилок, C++ прийняв угоду про використання файлів заголовків для зберігання об'яв. Ви робите оголошення у файлі заголовка, а потім використовуйте директиву #include у кожному файлі .cpp або іншому файлі заголовка, який вимагає оголошення. Директива #include вставляє копію файлу заголовка безпосередньо у файл .cpp перед компіляцією.

У Visual Studio 2019 функція модулів C++20 представлена ​​як поліпшення та остаточна заміна файлів заголовків . Додаткові відомості див. у розділі "Загальні відомості про модулі C++".

приклад

У наступному прикладі показано загальний спосіб оголошення класу та його використання в іншому вихідному файлі. Почнемо з файлу заголовка, my_class.h. Він містить визначення класу, але зверніть увагу, що визначення є неповним; Функція-член do_something не визначена:

// my_class.h namespace N <class my_class <public: void do_something(); >; >

Потім створіть файл реалізації (зазвичай із .cpp або аналогічним розширенням). Ми викличемо файл my_class.cpp та надайте визначення для оголошення члена. Ми додамо директиву #include для файлу "my_class.h", щоб оголошення my_class вставлялося в цей момент у файл .cpp, і ми включаємо оголошення std::cout . Зверніть увагу, що лапки використовуються для файлів заголовків у тому ж каталозі, що й вихідний файл, а для заголовків стандартної бібліотеки використовуються кутові дужки. Крім того, багато заголовків стандартної бібліотеки не мають розширення H або інших файлів.

У файлі реалізації можна використовувати using інструкцію, щоб уникнути необхідності кваліфікувати кожну згадку "my_class" або "cout" з "N::" або "std::". Не розміщуйте using інструкції до файлів заголовків!

// my_class.cpp #include "my_class.h" // header in local directory #include // header in standard library using namespace N; using namespace std; void my_class::do_something()

Ми можемо використовувати my_class в іншому .cpp файлі. Ми маємо #include файл заголовка, щоб компілятор витягував оголошення. Все, що компілятор повинен знати, є те, що my_class є класом, який має загальнодоступну do_something() функцію-член.

// my_program.cpp #include "my_class.h" using namespace N; int main()

Після завершення компіляції кожного файлу .cpp у файли .obj компілятор передає .obj файли компонувальнику.При злитті компонувальника файлів об'єктів він знаходить одно визначення для my_class; він знаходиться у файлі .obj, що створюється для my_class.cpp, і збірка завершується успішно.

Включення охоронців

Як правило, файли заголовків мають параметр include guard або директиву #pragma once щоб переконатися, що вони не вставляються кілька разів в один файл .cpp.

// my_class.h #ifndef MY_CLASS_H // include guard #define MY_CLASS_H namespace N < class my_class < public: void do_something(); >; > #endif /* MY_CLASS_H */

Що потрібно помістити у файл заголовка

Оскільки файл заголовка може бути включений кількома файлами, він може містити визначення, які можуть створювати кілька визначень одного імені. Наступні дії не допускаються або вважаються дуже поганою практикою.

  • вбудовані визначення типів у просторі імен чи глобальної області
  • визначення функцій, відмінних від вбудованих
  • Визначення змінних, відмінні від const
  • агрегатні визначення
  • безіменні простори імен
  • Директиви

using Використання директиви не обов'язково призведе до помилки, але може викликати проблему, оскільки вона приносить простір імен в область у кожному файлі .cpp, який безпосередньо або опосередковано включає цей заголовок.

Приклад файлу заголовка

У наступному прикладі показано різні види оголошень та визначень, які дозволені у файлі заголовка:

// sample.h #pragma once #include // #include directive #include namespace N // namespace declaration < inline namespace P < //.>enum class colors : short < red, blue, purple, azure >; const double PI = 3.14; // const and constexpr definitions !"); // static_assert return MeaningOfLife; >using vstr = std::vector; // type alias extern double d; / regular class definition, < // but non-inline function definitions friend class other_class; void do_something(); / definition in my_class.cpp input r<0>; // member initialization short g<0>; template // template definition class value_store < public: value_store() = default; void write_value(T val) < //. >

Зворотній зв'язок

Чи корисні відомості на цій сторінці?

Урок №122. Класи та заголовні файли

На цьому уроці ми розглянемо роботу класів із заголовними файлами у мові С++.

Відділення оголошення від реалізації

Усі класи, які ми досі використовували, були досить простими, тому ми записували методи безпосередньо всередині тіла класів, наприклад:

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

На щастя, мова C++ надає спосіб відокремити "оголошення" від "реалізації". Це робиться шляхом визначення методів поза тілом самого класу. Для цього просто визначте методи класу, якби вони були звичайними функціями, але як префікс додайте до імені функції ім'я класу з оператором роздільної здатності видимості ( :: ).

Ось наш клас Date з конструктором Date() та методом setDate(), визначеними поза тілом класу. Зверніть увагу, прототипи цих функцій все ще знаходяться всередині тіла класу, але їх фактична реалізація знаходиться за його межами:

Просто, чи не так? Оскільки у багатьох випадках функції доступу можуть складатися всього з одного рядка коду, їх зазвичай залишають в тілі класу, хоча перемістити їх за межі класу можна завжди.

Ось ще один приклад класу з конструктором, певним ззовні, списком ініціалізації членів:

Класи та заголовні файли

На уроці про заголовних файлах у мові С++ ми дізналися, що оголошення функцій можна помістити в заголовні файли, щоб мати можливість використовувати ці функції в декількох файлах або навіть в декількох проектах. Класи у цьому плані нічим не відрізняються від функцій. Визначення класів можуть бути поміщені в заголовки для полегшення їх повторного використання в декількох файлах або проектах. Зазвичай визначення класу поміщається в заголовковий файл з тим же ім'ям, що у класу, а методи, визначені поза тілом класу, поміщаються у файл .cpp з тим же ім'ям, що у класу.

Ось наш клас Date, але вже розбитий на файли .cpp та .h:

Тепер будь-який інший файл .h або .cpp, який захоче використовувати клас Date, зможе просто підключити файл заголовка: #include "Date.h" . Зверніть увагу, що Date.cpp також необхідно додати до компіляції в проект, який використовує Date.h, щоб лінкер зміг розібратися з реалізацією класу Date.

Питання №1: «Хіба визначення класу в заголовку не порушує правило одного визначення?».

Ні. Класи - це типи даних користувача, які звільняються від визначення тільки в одному місці. Тому клас, визначений у заголовному файлі, можна вільно підключати до інших файлів.

Питання №2: «Чи визначення методів класу в заголовному файлі не порушує правило одного визначення?».

Методи, визначені усередині тіла класу, вважаються неявно вбудованими. Вбудовані функції звільняються від правила одного визначення. А це означає, що проблем із визначенням простих методів (таких як функції доступу) усередині самого класу виникати не повинно.

Методи, визначені поза тілом класу, розглядаються як звичайні функції і підпорядковуються правилу одного визначення, тому ці функції повинні бути визначені у файлі .cpp, а не всередині .h. Єдиним винятком є ​​шаблони функцій (але це трохи пізніше).

Параметри за замовчуванням

Параметри за замовчуванням для методів повинні бути оголошені в тілі класу (у файлі заголовка), де вони будуть видно всім, хто підключає цей заголовний файл з класом.

Бібліотеки

Розподіл оголошення класу та його реалізації дуже поширений у бібліотеках, які використовуються для розширення можливостей вашої програми.Ви також підключали такі заголовні файли зі стандартної бібліотеки С++, як iostream, string, vector, array та інші. Зверніть увагу, ви не додавали iostream.cpp, string.cpp, vector.cpp або array.cpp до ваших проектів. Ваша програма потребує лише оголошень із заголовних файлів, щоб компілятор зміг перевірити коректність вашого коду відповідно до правил синтаксису мови C++. Однак реалізації класів, що знаходяться в Стандартній бібліотеці С++, містяться в попередньо скомпільованому файлі, який додається на етапі лінкінгу. Ви ніде не зустрічаєте цей код.

Поза програмами з відкритим вихідним кодом (де надаються обидва файли: .h і .cpp), більшість сторонніх бібліотек надають лише заголовні файли разом із попередньо скомпільованим файлом бібліотеки. На це є кілька причин:

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

Захист інтелектуальної власності (творці не хочуть, щоб інші просто «крали» їхній код).

Наявність власних файлів, поділених на оголошення (файли .h) і реалізацію (файли .cpp), є не тільки гарною формою змісту коду, але й спрощує створення власних бібліотек користувача.

Висновок

Можливо, у вас виникне спокуса помістити всі визначення методів класу в файл заголовка всередині тіла класу. Хоча це скомпілюється, але тут є кілька нюансів:

По-перше, як згадувалося вище, це призведе до захаращення визначення вашого класу.

По-друге, функції, визначені всередині класу, неявно вбудовані.Великі функції, які викликаються з багатьох файлів, можуть сприяти, таким чином, "роздмухування" вашого коду.

По-третє, якщо ви зміните щось у заголовному файлі, то вам потрібно буде перекомпілювати кожен файл, який містить цей заголовок. Це може мати ефект метелика, коли одна незначна зміна змусить перекомпілювати всю програму (що може бути досить повільно і довго). Якщо ж ви змінили код у файлі .cpp, вам необхідно перекомпілювати тільки цей файл .cpp!

Тому рекомендується наступне:

Класи, що використовуються лише в одному файлі, і які не використовуються повторно, визначайте безпосередньо у файлі .cpp, де вони використовуються.

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

Тривіальні методи (звичайні конструктори або деструктори, функції доступу тощо) визначайте всередині тіла класу.

Нетривіальні методи визначайте у файлі .cpp з тим самим ім'ям, що у класу.

На наступних уроках більшість наших класів буде визначено у файлі .cpp з усіма методами, реалізованими безпосередньо в тілі класу. Це робиться для зручності та лаконічності прикладів. У реальних проектах краще, коли класи розміщуються в окремі файли .cpp і .h.

2.10 - Заголовні файли

У міру того, як програми стають більшими (і використовують більше файлів), стає все більш стомлюючим давати попередні оголошення кожної функції, яку ви хочете використовувати, і яка визначена в іншому файлі. Чи було б непогано, якби ви могли помістити всі свої попередні оголошення в одне місце, а потім імпортувати їх, коли вони вам знадобляться?

Вихідні файли коду C++ (з розширенням .cpp) – це єдині файли, які зазвичай зустрічаються у програмах на C++. Інший тип файлів – це заголовний файл (іноді просто заголовок). Заголовкові файли зазвичай мають розширення .h, але іноді ви можете зустріти їх з розширенням .hpp або взагалі без розширення. Основна мета заголовного файлу – розповсюджувати оголошення у вихідні файли коду.

Ключовий момент

Заголовні файли дозволяють нам розміщувати оголошення в одному місці, а потім імпортувати їх туди, де вони нам потрібні. Це може заощадити багато часу при наборі тексту в проектах із кількох файлів.

Використання заголовних файлів стандартної бібліотеки

Розглянемо таку програму:

Ця програма друкує Hello, world! в консоль за допомогою std::cout . Однак ця програма ніколи не надавала визначення або оголошення для std::cout, тому як компілятор дізнається, що таке std::cout?

Відповідь полягає в тому, що std::cout був попередньо оголошений у заголовному файлі "iostream". Коли ми пишемо #include, ми запитуємо, щоб препроцесор скопіював весь вміст (включаючи попередні оголошення для std::cout) з файлу з ім'ям iostream у файл, що виконує #include.

Ключовий момент

Коли ви включаєте файл за допомогою #include , вміст файлу вставляється в точці включення. Це зручний спосіб видалення оголошень з іншого файлу.

Подумайте, що сталося б, якби заголовок iostream не існував.Щоразу, коли ви хотіли б використовувати std::cout , вам доводилося вручну вводити або копіювати всі оголошення, пов'язані з std::cout , на початок кожного файлу, який використовував би std::cout ! Для цього знадобиться багато знань про те, як реалізований std::cout , і знадобиться багато роботи. Найгірше, якби прототип функції змінився, нам довелося б вручну оновлювати всі попередні оголошення. Набагато простіше просто включити iostream за допомогою #include!

Коли справа доходить до функцій та змінних, варто пам'ятати, що заголовні файли зазвичай містять лише оголошення функцій та змінних, а не їх визначення (інакше може статися порушення правила одного визначення). std::cout оголошено в заголовку iostream, але визначено як частину стандартної бібліотеки C++, яка автоматично підключається до вашої програми на етапі лінкеру.

Рисунок 1 – Діаграма процесу збирання

Найкраща практика

Заголовні файли зазвичай не повинні містити визначення функцій та змінних, щоб не порушувати правило одного визначення. Виняток зроблено для символьних констант (які ми розглянемо в уроці «4.14 – const, constexpr та символьні константи»).

Написання власних заголовних файлів

А тепер повернемося до прикладу, який ми обговорювали на попередньому уроці. Коли ми закінчили, у нас було два файли, add.cpp і main.cpp, які виглядали так:

#include int add(int x, int y); // Попереднє оголошення з використанням прототипу функції int main()

(Якщо ви відтворюєте цей приклад з нуля, не забудьте додати add.cpp до свого проекту, щоб він компілювався).

У цьому прикладі ми використовували попереднє оголошення, щоб компіляції main.cpp компілятор знав, що таке ідентифікатор add . Як згадувалося раніше, додавання попередніх оголошень для кожної функції, яку ви хочете використовувати і яка знаходиться в іншому файлі, вручну може швидко стати стомлюючим.

Давайте напишемо заголовний файл, щоб позбутися цього тягаря. Написати заголовковий файл напрочуд легко, оскільки файли заголовків складаються тільки з двох частин:

  1. захист заголовка, про який ми поговоримо докладніше у наступному уроці («2.11 – Захист заголовків»);
  2. фактичний вміст файлу заголовка, який має бути попередніми оголошеннями для всіх ідентифікаторів, які ми хочемо, щоб інші файли могли бачити.

Додавання заголовного файлу до проекту працює аналогічно доданню вихідного файлу (розглядається в уроці «2.7 – Програми з кількома файлами вихідного коду»). Якщо ви використовуєте IDE, виконайте такі ж дії і при появі запиту виберіть Файл заголовка (або C/C++ header) замість Файла С++ (або C/C++ source). Якщо ви використовуєте командний рядок, просто створіть новий файл у вашому улюбленому редакторі.

Найкраща практика

При назві файлів заголовків використовуйте розширення .h .

Заголовкові файли часто йдуть у парі з файлами вихідного коду, при цьому файл заголовка надає попередні оголошення для відповідного вихідного файлу. Оскільки наш заголовковий файл міститиме попереднє оголошення для функцій, визначених в add.cpp, ми назвемо наш новий заголовковий файл add.h.

Найкраща практика

Якщо заголовний файл йде в парі з файлом вихідного коду (наприклад, add.h з add.cpp), вони обидва повинні мати однакове базове ім'я (add).

Ось наш завершений заголовний файл:

// 1) У нас тут насправді має бути захист заголовка // але для простоти ми опустимо її (ми розглянемо захист заголовків у наступному уроці) // 2) Це вміст файлу .h, де йдуть оголошення int add(int x , int y); // прототип функції для add.h - не забудьте крапку з комою!

Щоб використовувати цей заголовковий файл у main.cpp , ми повинні включити його за допомогою #include (використовуючи лапки, а не кутові дужки).

#include // Вставляємо вміст add.h у цей момент. // Зверніть увагу використання тут подвійних лапок. #include "add.h" int main()

Коли препроцесор обробляє рядок #include "add.h", він копіює вміст add.h у поточний файл у цю точку. Оскільки наш add.h містить попереднє оголошення для функції add, це попереднє оголошення буде скопійовано в main.cpp. Кінцевим результатом є програма, яка функціонально аналогічна до тієї, в якій ми вручну додали попереднє оголошення вгорі main.cpp .

Отже, наша програма правильно компілюватиметься і компонуватиметься.

Рисунок 2 – Діаграма процесу збирання

Включення заголовного файлу у відповідний вихідний файл

Пізніше ви побачите, що більшість вихідних файлів включають свій відповідний файл заголовка, навіть якщо він їм не потрібен. Навіщо?

Включення заголовного файлу до вихідного файлу збільшує пряму сумісність. Цілком імовірно, що в майбутньому ви додасте більше функцій або зміните існуючі таким чином, що їм потрібно буде знати про існування один одного.

Коли ми заглибимося у вивчення стандартної бібліотеки, ви будете включати безліч файлів заголовків бібліотек. Якщо вам потрібно було ввімкнути заголовний файл, воно, ймовірно, знадобилося вам для оголошення функції. Це означає, що вам також буде потрібно таке ж включення у вихідний файл. Це призведе до того, що у вихідному файлі у вас буде копія включень заголовного файлу. Увімкнувши заголовний файл у вихідний файл, вихідний файл отримає доступ до всього, до чого мав доступ до заголовкового файлу.

При розробці бібліотеки включення заголовного файлу до вихідного файлу може навіть допомогти в ранньому виявленні помилок.

Найкраща практика

При написанні вихідного файлу увімкніть у нього відповідний заголовний файл (якщо він існує), навіть якщо він вам поки що не потрібен.

Пошук та усунення проблем

Якщо ви отримуєте помилку компілятора, що вказує на те, що add.h не знайдено, переконайтеся, що файл дійсно називається add.h . Залежно від того, як ви його створили та назвали, можливо, файл може мати ім'я на кшталт add (без розширення), add.h.txt або add.hpp. Також переконайтеся, що він знаходиться в тому ж каталозі, що й інші вихідні файли.

Якщо ви отримуєте повідомлення про помилку компонувальника про те, що додавання функції не визначено, переконайтеся, що ви додали до проекту файл add.cpp , щоб визначення функції add можна було з'єднати в програмі.

Кутові дужки та подвійні лапки

Вам, напевно, цікаво, чому ми використовуємо кутові дужки для iostream та подвійні лапки для add.h. Можливо, що заголовки з таким же ім'ям можуть існувати в декількох каталогах.Використання кутових дужок та подвійних лапок допомагає компілятору зрозуміти, де йому слід шукати заголовні файли.

Коли ми використовуємо кутові дужки, ми повідомляємо препроцесор, що це заголовний файл, який ми не писали самі. Компілятор буде шукати заголовок тільки в каталогах, вказаних у каталогах файлів, що включаються (include directories). Каталоги файлів, що включаються, налаштовуються як частина вашого проекту / налаштувань IDE / налаштувань компілятора і зазвичай за замовчуванням використовуються для каталогів, що містять заголовні файли, які поставляються з вашим компілятором та/або ОС. Компілятор не шукатиме заголовковий файл у каталозі вихідного коду вашого проекту.

Коли ми використовуємо подвійні лапки, ми повідомляємо препроцесору, що це заголовний файл, який ми написали. Компілятор спочатку шукатиме цей заголовковий файл у поточному каталозі. Якщо він не зможе знайти там відповідний заголовний файл, він буде шукати його в каталогах файлів, що включаються.

Правило

Використовуйте подвійні лапки, щоб включати заголовні файли, які ви написали або які, як очікується, будуть знайдені в поточному каталозі. Кутові дужки використовуйте, щоб включати заголовні файли, які постачаються з компілятором, ОС або сторонніми бібліотеками, які ви встановили в іншому місці своєї системи.

Чому iostream не має розширення .h ?

Інше питання, що часто ставиться: «Чому iostream (або будь-який інший заголовковий файл стандартної бібліотеки) не має розширення .h?». Відповідь полягає в тому, що iostream.h – це інший заголовний файл, який відрізняється від iostream! Для пояснення потрібний невеликий урок історії.

Коли C++ було створено, всі файли в стандартній бібліотеці закінчувалися розширенням .h . Життя було послідовним, і це було добре. Вихідні версії cout та cin були оголошені в iostream.h. Коли комітет ANSI стандартизував мову, вони вирішили перемістити всі функції стандартної бібліотеки в простір імен std, щоб уникнути конфліктів імен з ідентифікаторами користувача. Однак це представляло проблему: якби вони перемістили всю функціональність у простір імен std, жодна зі старих програм (включаючи iostream.h) більше не працювала б!

Щоб обійти цю проблему, був представлений новий набір файлів заголовка, які використовують ті ж імена, але не мають розширення .h . Усі функції цих нових заголовних файлах перебувають у просторі імен std . Таким чином, старі програми, що містять #include, не потрібно переписувати, а нові програми можуть використовувати #include.

Крім того, багато бібліотек, успадкованих від C, які все ще використовуються в C++, отримали префікс c (наприклад, stdlib.h став cstdlib). Функціональні можливості цих бібліотек також було перенесено у простір імен std , щоб уникнути конфліктів імен.

Найкраща практика

Якщо увімкнути заголовний файл зі стандартної бібліотеки, використовуйте версію без розширення (без .h ), якщо вона існує. Користувацькі заголовні файли, як і раніше, повинні використовувати розширення .h.

Увімкнення заголовних файлів з інших каталогів

Інше поширене питання пов'язане з тим, як включати заголовні файли з інших каталогів.

Один (поганий) спосіб зробити це – додати відносний шлях до файлу заголовка, який ви хочете включити як частину рядка #include . Наприклад:

#include "headers/myHeader.h" #include "../moreHeaders/myOtherHeader.h"

Хоча це буде компілюватися (за умови, що файли існують у цих відносних каталогах), зворотний бік цього підходу полягає в тому, що він вимагає від вас відображення структури каталогів у вашому коді. Якщо ви коли-небудь оновите структуру каталогів, ваш код більше не працюватиме.

Найкращий спосіб – повідомити ваш компілятор або IDE, що у вас є купа заголовних файлів в якомусь іншому місці, щоб він дивився туди, коли не може знайти їх у поточному каталозі. Зазвичай це можна зробити, встановивши шлях включення (include path) або каталог пошуку (search directory) у налаштуваннях проекту в IDE.

Для користувачів Visual Studio

Клацніть правою кнопкою миші на своєму проекті в браузері рішень і виберіть Властивості (Properties), потім вкладку Каталоги VC++.(VC++ Directories). Тут ви побачите рядок із назвою «Включені каталоги» (Include Directories). Додайте каталоги, в яких компілятор повинен шукати додаткові файли заголовків.

Для користувачів Code::Blocks

У Code:: Blocks перейдіть в меню Project (Проект) і виберіть Build Options (Параметри збирання), потім вкладку Search directories (Каталоги пошуку). Додайте каталоги, в яких компілятор повинен шукати додаткові файли заголовків.

Для користувачів GCC/G++

Використовуючи g++, ви можете використовувати параметр -I щоб вказати альтернативний каталог для включення.

g++ -o main -I/source/includes main.cpp

Гарний момент у цьому підході полягає в тому, що якщо ви коли-небудь зміните структуру каталогів, вам потрібно буде змінити лише одне налаштування компілятора або IDE, а не кожен файл коду.

Заголовні файли можуть містити інші заголовні файли

Зазвичай для заголовних файлів потрібно оголошення або визначення, яке знаходиться в іншому файлі заголовка. Через це заголовки часто включають за допомогою #include інші заголовки.

Коли ваш вихідний файл включає за допомогою #include перший заголовковий файл, ви також отримаєте будь-які інші заголовні файли, які були включені в перший заголовний файл (і будь-які заголовні файли, які були включені в попередні, і т.д.). Ці додаткові заголовки іноді називають «транзитивними включеннями», оскільки вони включаються неявно.

Вміст цих транзитивних включень доступний для використання у файлі вихідного коду. Однак не слід покладатись на вміст заголовків, які включені транзитивно. Реалізація файлів заголовка може з часом змінюватися або відрізнятися в різних системах. Якщо це станеться, ваш код може компілюватись лише на певних системах або може компілюватися зараз, але перестати в майбутньому. Цього легко уникнути, явно увімкнувши всі файли заголовків, необхідні для вмісту вашого файлу вихідного коду.

Найкраща практика

Кожен файл повинен явно включати з #include всі файли заголовків, необхідні для компіляції. Не покладайтеся на файли заголовків, включені транзитивно з інших заголовків.

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

Питання: Я не включив, і моя програма все одно працювала! Чому?

Це одне з найбільш поширених питань.Відповідь: швидше за все він працює, тому що ви включили якийсь інший заголовок (наприклад, ), який сам включає . Незважаючи на те, що ваша програма компілюватиметься, відповідно до наведених вище рекомендацій вам не слід покладатися на це. Те, що компілюється у вас, може не компілюватись на машині друга.

Порядок #include заголовних файлів

Якщо ваші файли заголовків написані правильно і включають з #include все, що їм потрібно, порядок включення не має значення. Однак включення заголовних файлів у певному порядку може допомогти виявити помилки, коли заголовні файли можуть не включати все, що їм потрібно.

Найкраща практика

Упорядкуйте свої включення з #include наступним чином: спочатку ваші власні заголовки, потім заголовки сторонніх бібліотек, потім заголовки стандартних бібліотек; заголовки у кожному розділі мають бути відсортовані за абеткою.

Таким чином, якщо в одному з ваших заголовків користувача немає #include для заголовка сторонньої бібліотеки або стандартної бібліотеки, це з більшою ймовірністю викличе помилку компіляції, щоб ви могли її виправити.

Рекомендації щодо використання заголовних файлів

Ось ще кілька рекомендацій щодо створення та використання заголовних файлів.

  • Завжди вмикайте захист заголовків (ми розглянемо це у наступному уроці).
  • Не визначайте змінні та функції у файлах заголовків (глобальні константи є винятком – ми розглянемо їх пізніше)
  • Давайте файлам заголовків ті ж імена, що й вихідним файлам, з якими вони пов'язані (наприклад, grades.h йде у парі grades.cpp ).
  • Кожен файл заголовка повинен мати конкретне призначення і бути максимально незалежним.Наприклад, ви можете помістити всі оголошення, що стосуються функціональності A , A.h , а всі оголошення, що стосуються функціональності B , B.h . Таким чином, якщо пізніше вам потрібен буде тільки A, ви можете просто включити A.h і не отримувати нічого, пов'язаного з B.
  • Враховуйте, які заголовки потрібно явно включити для функцій, які ви використовуєте у своїх файлах вихідного коду.
  • Кожен заголовок, який ви пишете, повинен компілюватися сам собою (він повинен включати з #include всі необхідні залежності)
  • Включайте з #include тільки те, що вам потрібно (не вмикайте все лише тому, що ви можете).
  • Не вмикайте з #include файли .cpp.

Схожі статті

  • Антибрик для корів Як зробити своїми руками Як правильно сплутати корову щоб можна було подоїти
  • Які пити вітаміни для того щоб завагітніти
  • Які ключі потрібні для того щоб зібрати велосипед
  • Які дезінфікуючі засоби можна використовувати для дезінфекції приміщень
  • Які способи можна використовувати для рекультивації ґрунту
  • Які документи потрібні щоб відкрити ресторан
  • Які документи потрібні для того щоб отримати паспорт
  • Що потрібно для того щоб відкрити пункт прийому металобрухту
  • Недавні статті

  • Як бродить зернова брага
  • Що робити якщо не засмагаєш на сонці чому засмага погано лягає на шкіру або перестає прилипати
  • Як швидко зняти гель лак без апарату
  • Як робиться Каті голови
  • Яка гребінець краще для об'єму
  • Чим роблять м'яку покрівлю
  • Чи можна залишати крем для обличчя на ніч
  • Де знаходиться датчик селектора
  • географія нашої діяльності
    вулиця Драгоманова, 27
    вул. Курчатова 1Б
    вул. Міцкевича 130
    вул. Лабунського, 1
    вул. Макарова-Пржевальського
    вул. Толстого 10
    вул. Грушевського 28
    вул. Перший промінь (Черняхівського)
    напишіть нам

    сообщение успешно отправлено
    x