Спочатку зверніться до свого першого запиту:
Коли ви бачите це у .h файлі:
#ifndef FILE_H
#define FILE_H
/* ... Declarations etc here ... */
#endif
Це препроцесорна методика запобігання включенню заголовкового файлу кілька разів, що може бути проблематичним з різних причин. Під час компіляції вашого проекту складається .cpp- файл (як правило). Простіше кажучи, це означає, що компілятор візьме ваш .cpp- файл, відкриє будь-які файли #included
ним, об'єднає їх у один масивний текстовий файл, а потім виконає аналіз синтаксису і, нарешті, він перетворить його в якийсь проміжний код, оптимізує / виконає інший задач і, нарешті, генерувати висновок збірки для цільової архітектури. Через це, якщо файл #included
кілька разів під одним .cppФайл, компілятор додасть вміст його файлу двічі, тож якщо в цьому файлі є визначення, ви отримаєте помилку компілятора, яка скаже вам, що ви переглянули змінну. Коли файл обробляється на етапі препроцесора в процесі компіляції, при першому досягненні його вмісту перші два рядки перевірять, чи FILE_H
було визначено для препроцесора. Якщо ні, він визначить FILE_H
і продовжить обробку коду між ним та #endif
директивою. Наступного разу, коли вміст файлу побачить препроцесор, перевірка проти FILE_H
буде помилковою, тому він буде негайно сканувати до #endif
та продовжувати після нього. Це запобігає помилкам переосмислення.
І щоб вирішити вашу другу проблему:
У програмі на C ++ як загальній практиці ми розділяємо розробку на два типи файлів. Один з розширенням .h, і ми називаємо це "файлом заголовка". Зазвичай вони надають декларацію функцій, класів, структур, глобальних змінних, typedefs, попередньої обробки макросів та визначень тощо. В основному вони просто надають вам інформацію про ваш код. Тоді у нас є розширення .cpp, яке ми називаємо "кодовим файлом". Це дасть визначення для тих функцій, членів класу, будь-яких членів структури, яким потрібні визначення, глобальних змінних тощо. Отже, файл .h оголошує код, а файл .cpp реалізує цю декларацію. З цієї причини ми, як правило, під час компіляції компілюємо кожен .cppфайл у об’єкт, а потім з'єднайте ці об’єкти (оскільки ви майже ніколи не бачите .cpp- файл включає інший .cpp- файл).
Як вирішуються ці зовнішні програми, це робота для лінкера. Коли ваш компілятор обробляє main.cpp , він отримує декларації для коду в class.cpp , включаючи class.h . Потрібно лише знати, як виглядають ці функції чи змінні (що саме дає вам декларація). Отже, він компілює ваш файл main.cpp у якийсь об’єктний файл (називайте його main.obj ). Аналогічно, class.cpp компілюється в class.objфайл. Для отримання остаточного виконуваного файлу викликається посилання для з'єднання цих двох об'єктних файлів разом. Для будь-яких невирішених зовнішніх змінних чи функцій компілятор розмістить заглушку, де відбувається доступ. Потім линкер візьме цю заглушку і шукатиме код або змінну в іншому перерахованому об'єктному файлі, і якщо він знайдений, він об'єднує код з двох об'єктних файлів у вихідний файл і замінює заглушку на остаточне розташування функції або змінна. Таким чином, ваш код у main.cpp може викликати функції та використовувати змінні у class.cpp ЯКЩО ТА ТІЛЬКИ, ЯКЩО ВІДГОТОВЛЕНО В class.h .
Я сподіваюся, що це було корисно.