Что такое форвардные объявления В C++?



At:http://www.learncpp.com/cpp-tutorial/19-header-files/



следующее:

добавить.cpp:



int add(int x, int y)
{
return x + y;
}


главная.cpp:



#include <iostream>

int add(int x, int y); // forward declaration using function prototype

int main()
{
using namespace std;
cout << "The sum of 3 and 4 is " << add(3, 4) << endl;
return 0;
}



мы использовали прямое объявление, чтобы компилятор знал, что"add" был при компиляции main.cpp. Как уже упоминалось ранее, написание прямых объявлений для каждой функции, которую вы хотите использовать, которая живет в другом файле, может стать утомительным быстро.




вы можете объяснить "вперед декларации" в дальнейшем? В чем проблема, если мы используем его в

1031   8  

8 ответов:

почему forward-declare необходимо в C++

компилятор хочет убедиться, что вы не допустили орфографических ошибок или не передали неверное количество аргументов функции. Таким образом, он настаивает на том, что он сначала видит объявление " add " (или любые другие типы, классы или функции) перед его использованием.

это действительно просто позволяет компилятору лучше выполнять проверку кода и позволяет ему убирать свободные концы, чтобы он мог создавать аккуратный объект файл. Если бы вам не нужно было пересылать объявления, компилятор создал бы объектный файл, который должен был бы содержать информацию обо всех возможных догадках относительно того, что может быть функцией "add". И компоновщик должен был бы содержать очень умную логику, чтобы попытаться выяснить, какое "добавить" вы на самом деле намеревались вызвать, когда функция "Добавить" может жить в другом объектном файле, который компоновщик объединяет с тем, который использует add для создания dll или exe. Вполне возможно, что компоновщик может получить неправильно добавляют. Скажем, вы хотели использовать int add(int a, float b), но случайно забыли его написать, но компоновщик нашел уже существующий int add(int a, int b) и подумал, что это правильный и использовал его вместо этого. Ваш код будет компилироваться, но не будет делать то, что вы ожидали.

Итак, просто чтобы сохранить вещи явными и избежать угадывания и т. д., компилятор настаивает, чтобы вы объявили все, прежде чем он будет использоваться.

разница между объявлением и определение

кроме того, важно знать разницу между объявлением и определением. Объявление просто дает достаточно кода, чтобы показать, как что-то выглядит, поэтому для функции это тип возврата, соглашение о вызове, имя метода, Аргументы и их типы. Но код для метода не требуется. Для определения вам нужно объявление, а затем и код для функции тоже.

как вперед-объявления могут значительно сократить время сборки

Вы можете получить объявление функции в текущий .cpp или .файл H с #, в том числе выставление заголовка, который содержит объявление функции. Однако это может замедлить компиляцию, особенно если вы #включаете заголовок в a .ч вместо .cpp вашей программы, как и все, что #включает в себя .h вы пишете в конечном итоге #include'ING все заголовки, которые вы написали #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;
};

Файл Колесо.h

Мда... декларация автомобиля требуется здесь, так как колесо имеет указатель на автомобиль, но автомобиль.h не может быть включен здесь, поскольку это приведет к ошибке компилятора. Если Автомобиль.H был включен, что бы потом попытаться включить колесо.h который будет включать автомобиль.h который будет включать колесо.ч и это будет продолжаться вечно, поэтому компилятор выдает ошибку. Решение состоит в том, чтобы переслать объявить автомобиль вместо этого:

class Car;     // forward declaration

class Wheel
{
    Car* car;
};

Если класс Wheel имеет методы, которые должны вызывать методы car, эти методы могут быть определены в Wheel.cpp и колеса.cpp теперь может включать автомобиль.h не вызывая цикла.

компилятор ищет каждый символ, используемый в текущей единице перевода, ранее объявленной или нет в текущей единице. Это просто вопрос стиля, обеспечивающего все сигнатуры метода в начале исходного файла, а определения предоставляются позже. Значительное его использование - это когда вы используете указатель на класс в качестве переменной-члена другого класса.

//foo.h
class bar;    // This is useful
class foo
{
    bar* obj; // Pointer or even a reference.
};

// foo.cpp
#include "bar.h"
#include "foo.h"

Итак, используйте forward-объявления в классах, когда это возможно. Если ваша программа не имеет функции( с файлами заголовков ho), то предоставление прототипов в начале-это просто вопрос стиля. Это было бы так или иначе, если бы файл заголовка присутствовал в обычной программе с заголовком, который имеет только функции.

поскольку C++ анализируется сверху вниз, компилятор должен знать о вещах, прежде чем они будут использоваться. Итак, когда вы ссылаетесь:

int add( int x, int y )

в основные функции компилятор должен знать, что он существует. Чтобы доказать это, попробуйте переместить его ниже основной функции, и вы получите ошибку компилятора.

Так a'Вперед Декларации это как раз то, что написано на жестянке. Он объявляет что-то заранее о своем использовании.

в целом, вы должны включить переслать объявления в заголовочный файл, а затем включить этот файл заголовка таким же образом, что iostream входит в комплект.

термин "вперед декларации" в C++ в основном используется только для декларациях класс. Смотри (конец) ответ почему "прямое объявление" класса на самом деле просто декларации класс с причудливым именем.

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

(Что касается того, что такое декларация в противоположность определение, вновь увидеть в чем разница между определением и объявлением?)

когда компилятор видит add(3, 4) Он должен знать, что это значит. С помощью прямого объявления вы в основном говорите компилятору, что add - это функция, которая принимает два int и возвращает int. Это важная информация для компилятора, потому что он должен поместить 4 и 5 в правильное представление в стек и должен знать, какого типа вещь возвращается add.

В то время, компилятор не беспокоится о фактический реализация add, т. е. где он находится (или если есть и еще один) и если он компилирует. Это будет видно позже,после компиляция исходных файлов при вызове компоновщика.

int add(int x, int y); // forward declaration using function prototype

можете ли вы объяснить " вперед объявление" еще дальше? В чем проблема если мы используем его в функции main ()?

это же #include"add.h". Если вы знаете,препроцессор расширяет файл, который вы упоминаете в #include, в рамках .cpp файл, где вы пишите

одна проблема в том, что компилятор не знает, какое значение передается функции; это предполагает, что функция возвращает int в этом случае, но это может быть как правильно, так и неправильно. Другая проблема заключается в том, что компилятор не знает, какие аргументы функция ожидает, и не может предупредить вас, если вы передаете ценности не те. Существуют специальные правила "продвижения", которые применяются при передаче, скажем, значений с плавающей запятой необъявленным функция (компилятор должен расширить их до типа double), что часто не является тем, что функция действительно ожидает, что приводит к трудному поиску ошибок во время выполнения.

одно быстрое добавление относительно: обычно вы помещаете эти ссылки вперед в файл заголовка, принадлежащий.C (pp) файл, где функция/переменная и т. д. реализованный. в вашем примере это будет выглядеть так: добавлять.h:

extern int add(int a, int b);

ключевое слово extern указывает, что функция фактически объявлена во внешнем файле (также может быть библиотека и т. д.). ваш главный.С будет выглядеть так:

#include 
#include "add.h"

int main()
{
.
.
.

Comments

    Ничего не найдено.