Чому вперед потрібно оголосити в C ++
Компілятор хоче переконатися, що ви не допустили орфографічних помилок або передали неправильну кількість аргументів функції. Отже, він наполягає на тому, що він спочатку бачить декларацію "додати" (або будь-які інші типи, класи або функції) перед її використанням.
Це дійсно просто дозволяє компілятору виконати кращу роботу з перевірки коду і дозволяє йому виправити вільні кінці, щоб він міг створити акуратний об’єктний файл. Якщо вам не потрібно було пересилати декларування речей, компілятор видав би об'єктний файл, який повинен містити інформацію про всі можливі здогадки про те, якою може бути функція "додати". І для того, щоб функція "add" могла жити в іншому об'єктному файлі, він може містити дуже розумну логіку, щоб спробувати розробити "додавання", коли функція "add" може жити в іншому об'єктному файлі. dll або exe. Можливо, що лінкер може отримати неправильне додавання. Скажіть, ви хотіли використовувати int add (int a, float b), але випадково забули його написати, але лінкер знайшов уже існуючий додаток int (int a, int b) і вважав, що це правильно, і використовував це замість цього. Ваш код збирається, але не буде робити те, що ви очікували.
Таким чином, лише для того, щоб все було явним і уникати здогадок тощо, компілятор наполягає на тому, щоб ви оголосили все до того, як воно буде використано.
Різниця між декларацією та визначенням
Як осторонь, важливо знати різницю між декларацією та визначенням. Декларація просто дає достатньо коду, щоб показати, як щось виглядає, тому для функції це тип повернення, умовний виклик, назва методу, аргументи та їх типи. Але код методу не потрібен. Для визначення вам потрібна декларація, а потім і код функції.
Як вперед-декларації можуть значно скоротити терміни складання
Ви можете отримати декларацію функції у свій поточний .cpp або .h файл, # включивши заголовок, який вже містить оголошення функції. Однак це може уповільнити компіляцію, особливо якщо ви #include заголовок у .h замість .cpp вашої програми, оскільки все, що # включає в себе .h, що ви пишете, закінчилося б # включаючи всі заголовки. Ви теж написали #includes. Раптом у компілятора є # включені сторінки та сторінки коду, які йому потрібно зібрати, навіть коли ви хотіли використовувати лише одну або дві функції. Щоб цього уникнути, ви можете використовувати переадресацію та просто ввести декларацію функції самостійно у верхній частині файлу. Якщо ви використовуєте лише декілька функцій, це дійсно може зробити ваші компіляції швидшими порівняно з завжди # включенням заголовка. Для дійсно великих проектів,
Розбийте циклічні посилання, де два визначення обидва використовують один одного
Крім того, вперед-декларації можуть допомогти вам порушити цикли. Тут обидві функції обидва намагаються використовувати одна одну. Коли це станеться (і це цілком дійсна річ), ви можете # включити один заголовочний файл, але цей заголовок намагається #including файл заголовка, який ви зараз пишете .... що потім #includes інший заголовок , яка # включає ту, яку ви пишете. Ви застрягли в ситуації з куркою і яйцями, коли кожен файл заголовка намагається повторно включити інший. Щоб вирішити це, ви можете переслати декларувати потрібні вам частини в одному з файлів і залишити #include з цього файлу.
Наприклад:
Файл Car.h
#include "Wheel.h" // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
std::vector<Wheel> wheels;
};
Файл Wheel.h
Хм ... тут потрібна декларація про автомобіль, оскільки Wheel має вказівник на Автомобіль, але Car.h сюди не може бути включений, оскільки це призведе до помилки компілятора. Якщо Car.h був включений, то він би спробував включити Wheel.h, який би включав Car.h, який включав би Wheel.h, і це продовжуватиметься назавжди, тому натомість компілятор викликає помилку. Рішення полягає в тому, щоб переадресувати заявку Авто замість цього:
class Car; // forward declaration
class Wheel
{
Car* car;
};
Якщо клас Wheel мав методи, які потрібно викликати автомобільними методами, ці методи можна було б визначити в Wheel.cpp, а Wheel.cpp тепер може включати Car.h, не викликаючи циклу.