Функции
Функция определяет действия, которые выполняет программа. Функции позволяют выделить набор инструкций и назначить ему имя. А затем многократно по присвоенному имени вызывать в различных частях программы. По сути функция — это именованный блок кода.
Формальное определение функции выглядит следующим образом:
тип имя_функции(параметры)
Первая строка представляет заголовок функции. Вначале указывается возвращаемый тип функции. Если функция не возвращает никакого значения, то используется тип void .
Затем идет имя функции, которое представляет произвольный идентификатор. К именованию функции применяются те же правила, что и к именованию переменных.
После имени функции в скобках идет перечисление параметров. Функция может не иметь параметров, в этом случае указываются пустые скобки.
После заголовка функции в фигурных скобках идет тело функции, которое содержит выполняемые инструкции.
Для возвращения результата функция применяет оператор return . Если функция имеет в качестве возвращаемого типа любой тип, кроме void, то она должна обязательно с помощью оператора return возвращать какое-либо значение.
Например, определение функции main, которая должна быть в любой программе на языке C++ и с которой начинается ее выполнение:
int main()
Возвращаемым типом функции является тип int , поэтому функция должна использовать оператор return и возвращать какое-либо значение, которое соответствует типу int. Возвращаемое значение ставится после оператора return.
Стоит отметить, что С++ позволяет не использовать оператор return в функции main:
int main()
Но если функция имеет тип void , то ей не надо ничего возвращать. Например, мы могли бы определить следующую функцию, которая просто выводит некоторый текст на консоль:
void hello()
Выполнение функции
Когда запускается программа на языке C++, то запускается функция main. Никакие другие функции, определенные в программе, автоматически не выполняются. Для выполнения функции ее необходимо вызвать. Вызов функции осуществляется в форме:
имя_функции(аргументы);
После имени функции указываются скобки, в которых перечисляются аргументы — значения для параметров функции.
Например, определим и выполним простейшую функцию:
#include void hello() < std::cout int main()
Здесь определена функция hello, которая вызывается в функции main два раза. В этом и заключается преимущество функций: мы можем вынести некоторые общие действия в отдельную функцию и затем вызывать многократно в различных местах программы. В итоге программа два раза выведет строку «hello».
hello hello
Объявление функции
При использовании функций стоит учитывать, что компилятор должен знать о функции до ее вызова. Поэтому вызов функции должен происходить после ее определения, как в случае выше. В некоторых языках это не имеет значение, но в языке C++ это играет большую роль. И если, к примеру, мы сначала вызовем, а потом определим функцию, то мы получим ошибку на этапе компиляции, как в следующем случае:
#include int main() < hello(); hello(); >void hello()
В этом случае перед вызовом функции надо ее дополнительно объявить. Объявление функции еще называют прототипом. Формальное объявление выглядит следующим образом:
тип имя_функции(параметры);
Фактически это заголовок функции. То есть для функции hello объявление будет выглядеть следующим образом:
void hello();
Используем объявление функции:
#include void hello(); int main() < hello(); hello(); >void hello()
В данном случае несмотря на то, что определение функции идет после ее вызова, но так как функция уже объявлена до ее вызова, то компилятор будет знать о функции hello, и никаких проблем в работе программы не возникнет.
Разница между объявлением и определением в C и C++
В C и C++ есть маленькое, но важное различие между значением слов “объявление” и “определение”. Если вы не понимаете разницы, иногда вы будете получать странные ошибки, такие как:
undefined symbol foo
undefined reference to foo
undefined reference to vtable for foo(в C++)
Что означает “объявление” в C и C++
При объявлении переменной, функции или даже класса все, что вы делаете, это говорите компилятору, что есть что-то с определенным именем и определенного типа. Компилятор может обрабатывать большинство (но не все) использований этого имени, без необходимости полного определения этого имени. Объявление значения, не определяя его, позволяет писать код, понятный компилятору, опуская дополнительные детали. Это особенно полезно, если вы работаете с несколькими исходными файлами и должны использовать функцию в нескольких файлах. Вам не нужно писать тело функции в каждом из файлов, но вы должны объявить ее.
Итак, как же выглядит объявление?
Например, если вы пишете:
int func();
Это объявление функции, оно не включает тело функции, но оно сообщает компилятору, что он может использовать эту функцию, и ожидать, что она будет определена где-то позже.
Что это значит, определить что-то в C и C++ ?
Определение чего-то означает предоставление всей необходимой информации для создания этого целиком. Определение функции означает предоставление тела функции, определение класса означает предоставление всех методов и полей класса. Как только что-то определено, оно также считается объявленным, так что вы можете как объявлять, так и определять функции, классы или переменные одновременно. Но вам это не нужно.
Например, для компилятора часто достаточно объявления. Вы можете написать такой код:
int func(); int main() < int x = func(); >int func()
Так как компилятор знает возвращаемое значение функции, и количество аргументов, которые она принимает, он может скомпилировать вызов функции, даже если она еще не определена. В самом деле, определение функции может быть в другом файле!
Вы также можете объявить класс не определяя его:
class MyClass;
Код, которому нужно знать детали того, что находится в MyClass не будет работать — вы не можете этого сделать:
class MyClass; MyClass an_object; class MyClass < int _a_field; >;
Потому что компилятор должен знать размер переменной an_object, и он не может узнать его из объявления MyClass; ему нужно определение, которое появляется ниже.
Объявление и определение переменных с Extern
В большинстве случаев, когда вы объявляете переменную, вы также определяете ее. Так что же такое определение переменной? Это означает, что вы говорите компилятору, где выделить место для этой переменной. Например, если вы пишете:
int x; int main()
Строка int х , как объявляет так и определяет переменную, она говорит: «создать переменную с именем х , типа int . Кроме того, место хранения переменной определяется тем, что это глобальная переменная, определенная в объектный файл, связанный с этим исходным файлом. Это немного странно, не правда ли? Что произойдет, если кто-то другой напишет второй исходный файл, который имеет такой код:
extern int x; int func()
Использование extern позволяет объявить переменную, не определяя ее, он сообщает, что переменная находится где-то в другом месте. Технически, можно даже написать такой код:
extern int x; int func() < x = 3; >int x;
И таким образом, объявление х находится в верхней части программы, а определение внизу. Но, как правило, extern используется, когда вы хотите получить доступ к глобальной переменной, объявленной в другом исходном файле, как я показал выше, а затем связать два получившихся объектных файла вместе после компиляции. Использование extern для объявления глобальной переменной в значительной степени то же самое, что и, используя объявление функции, объявить функцию в заголовке файла. (На самом деле, вы ставите extern в заголовке файла, а не в исходном файле.)
В самом деле, если вы поставите переменную в заголовке файла и не будете использовать extern , вы столкнетесь с обратной задачей неопределенного символа, у вас будет символ с несколькими определениями, с ошибкой типа:
redefinition of ‘foo
Это произойдет, когда компоновщик будет связывать объектные файлы.
Разница между объявлением и определением: Вывод
Объявление предоставляет основные свойства символа: его тип и его название. Определение предоставляет все детали этого символа — если это функция, что она делает; если это класс, какие у него поля и методы; если это переменная, где эта переменная находится. Часто, компилятору нужно объявление, чтобы скомпилировать файл в объектный файл, так как компоновщик может найти определение из другого файла. Если исходный файл не определяет символ, но он объявлен, во время компоновки вы будете получать ошибки, сообщающие о неопределенных символах.
Общие случаи
Если вы хотите использовать функцию в нескольких исходных файлах, вы должны объявить функцию в одном заголовочном файле (.h), а затем определить функцию в одном исходном файле (.c или .cpp). Весь код, который использует функцию должен включать в себя только .h файл, и вам надо связать полученные объектные файлы с объектным файлом от компиляции исходного файла.
Если вы хотите использовать класс в нескольких файлах, вы должны поместить определение класса в заголовочный файл и определить методы класса в соответствующем исходном файле. (Вы также можете использовать встроенные функции для методов).
Если вы хотите использовать переменную в нескольких файлах, вы должны объявить переменную с помощью ключевого слова extern в одном заголовочном файле, а затем включить этот заголовочный файл во все исходные файлы, которым нужна эта переменная. Затем вы должны определить эту переменную в одном исходном файле, который связан со всеми объектными файлами, которые используют эту переменную.
Объявления и определения (C++)
Программа C++ состоит из различных сущностей, таких как переменные, функции, типы и пространства имен. Перед их использованием необходимо объявить каждую из этих сущностей. Объявление указывает уникальное имя сущности, а также сведения о его типе и других характеристиках. В C++ точка объявления имени — это точка, в которой она становится видимой компилятору. Вы не можете ссылаться на функцию или класс, объявленный в какой-то момент в единице компиляции. Переменные должны объявляться как можно ближе до точки, в которой они используются.
В следующем примере показаны некоторые объявления:
#include int f(int i); // forward declaration int main() < const double pi = 3.14; //OK int i = f(2); //OK. f is forward-declared C obj; // error! C not yet declared. std::string str; // OK std::string is declared in header j = 0; // error! No type specified. auto k = 0; // OK. type inferred as int by compiler. > int f(int i) < return i + 42; >namespace N < class C*. */>; >
В строке 5 main функция объявляется. В строке 7 const переменная с именем pi объявлена и инициализирована . В строке 8 целое число i объявляется и инициализируется со значением, созданным функцией f . Имя f видно компилятору из-за объявления пересылки в строке 3.
В строке 9 объявлена переменная типа obj C . Однако это объявление вызывает ошибку, так как C не объявляется до конца программы и не объявляется перенаправленным. Чтобы устранить ошибку, можно переместить все определение C до main или добавить для него объявление вперед. Это поведение отличается от других языков, таких как C#. На этих языках функции и классы можно использовать до их точки объявления в исходном файле.
В строке 10 объявлена переменная типа str std::string . Имя std::string видно, так как оно представлено в string файле заголовка, который объединяется в исходный файл в строке 1. std — это пространство имен, в котором string объявлен класс.
В строке 11 возникает ошибка, так как имя j не было объявлено. Объявление должно предоставлять тип, в отличие от других языков, таких как JavaScript. В строке 12 auto используется ключевое слово, которая сообщает компилятору определить тип k на основе значения, с которым оно инициализировано. Компилятор в этом случае выбирает int тип.
Область видимости объявления
Имя, введенное объявлением, допустимо в область, где происходит объявление. В предыдущем примере переменные, объявленные внутри main функции, являются локальными переменными. Можно объявить другую переменную, именуемую i за пределами основной, в глобальной область, и она будет отдельной сущностью. Однако такое дублирование имен может привести к путанице и ошибкам программиста, и их следует избежать. В строке 21 класс C объявляется в область пространства N имен. Использование пространств имен помогает избежать конфликтов имен. Большинство имен стандартной std библиотеки C++ объявляются в пространстве имен. Дополнительные сведения о взаимодействии правил область с объявлениями см. в разделе «Область».
Определения
Некоторые сущности, включая функции, классы, перечисления и постоянные переменные, должны быть определены, а также объявлены. Определение предоставляет компилятору все сведения, необходимые для создания машинного кода при последующем использовании сущности в программе. В предыдущем примере строка 3 содержит объявление для функции f , но определение функции предоставляется в строках 15–18. В строке 21 класс объявлен и определен (хотя как определено, класс C ничего не делает). Константная переменная должна быть определена, другими словами, присвоено значение в той же инструкции, в которой она объявлена. Объявление встроенного типа, например автоматическое определение, так как int компилятор знает, сколько пространства для него выделяется.
В следующем примере показаны объявления, которые также являются определениями:
// Declare and define int variables i and j. int i; int j = 10; // Declare enumeration suits. enum suits < Spades = 1, Clubs, Hearts, Diamonds >; // Declare class CheckBox. class CheckBox : public Control < public: Boolean IsChecked(); virtual int ChangeState() = 0; >;
Ниже приведены некоторые объявления, которые не являются определениями:
extern int i; char *strchr( const char *Str, const char Target );
Операторы Typedefs и using
В более ранних версиях C++ typedef ключевое слово используется для объявления нового имени, которое является псевдонимом другого имени. Например, тип std::string — это другое имя. std::basic_string Очевидно, почему программисты используют имя typedef, а не фактическое имя. В современном C++ using ключевое слово предпочтительнее typedef , но идея аналогична: новое имя объявляется для сущности, которая уже объявлена и определена.
Статические члены класса
Элементы данных статического класса являются дискретными переменными, общими для всех объектов класса. Так как они совместно используются, они должны быть определены и инициализированы вне определения класса. Дополнительные сведения см. в разделе «Классы».
объявления экстернов
Программа C++ может содержать несколько единиц компиляции. Чтобы объявить сущность, определенную в отдельном модуле компиляции, используйте extern ключевое слово. Сведения в объявлении достаточно для компилятора. Однако если определение сущности не удается найти на шаге связывания, компоновщик вызовет ошибку.
Объявление? Определение? Инициализация?

В чем разница между объявлением переменной, её определением и инициализацией
Начинающим программистам первое время бывает трудно запомнить все те названия и термины, которые обрушиваются на них из учебников и современных вебинаров. Особенно, если они еще чем-то похожи между собой.
Такими близкими по смыслу и довольно часто путающимися являются понятия «объявление» переменной, её «определение» и её «инициализация».
В силу некоторой личной привычки я иногда фиксирую результаты гугления по тому или иному вопросу, связанному с обучением, в небольших конспектах. Это помогает разобраться в материале, систематизировать его и по-своему, более удобно для себя изложить. В дальнейшем такие записи помогают быстро повторить пройденный материал и являются своеобразным альтернативным вариантом изложения той или иной учебной темы.
И поскольку мы живем в жутко социализированное время, то естественно хочется поделиться результатами своего труда с другими,такими же начинающими программистами. Возможно кому-то это тоже пригодится.
Объявление переменной или константы
Итак, выражение называется объявлением переменной или декларированием. На английском это выглядит так — Declaring Constants and Variables:
var a = 10
В приведенном примере задана переменная (var), задано имя переменной (а) и задано значение переменной (10).
Определение переменной или константы
Как известно, объявить переменную мы можем и без указания значения. Но тогда нужно указать тип данных будущего значения.
var b: Int?
Вспомним, зачем это делается. Если в первом случае мы сразу указываем значение, то Swift автоматом определяет тип данных значения. Если же значение не указано, то Swift не знает, какого типа данные в ней будут храниться и ему нужно явно указать этот тип.
Заодно и еще один термин — аннотация типа. Это вот как раз результат действия по определению, а именно слово Int?.
Аннотация типа может быть простая, состоящая из одного слова, обозначающая тип данных, так и составная. Например, в кортежах (tuples) может быть и такая запись
var b: (Int, Int, Int)
И кстати, для чистоты кода в Swift рекомендуется не ставить пробел между именем переменной и двоеточием.
Инициализация переменной или константы
В первом примере, который мы продублируем ниже, где происходит не только объявление переменной, но и её инициализация:
var a = 10
Инициализация означает, что переменная запущена в работу, ей присвоено начальное значение, она инициализирована. Без присвоения начального значения переменная просто объявлена, а с начальным значением она еще и инициализирована.
Во втором случае, когда переменная объявлена без начального значения, т.е. она еще не инициализирована, не готова полностью к работе.
var b: Int
Три действия — объявление, определение, инициализация
Таким образом, мы имеем здесь три действия — объявление, определение и инициализацию. Их можно записать в одном выражении:
var a: Int = 10
Но, как мы помним, Swift рекомендует экономить время, если есть значение, он может самостоятельно определить тип данных.
И еще, обратите внимание, что голого объявления переменной не может быть. Должно быть обязательно объявление с какой-то второй операцией — или с присвоением значения или с определением типа данных значения. И можно применять сразу три действия, но нельзя только одно, т.е. больше можно, меньше нельзя.
Ковбойская история
Разницу между этими тремя действиями можно проиллюстрировать с помощью шуточного примера, найденного на просторах интернета и немного подредактированного))
Итак, в бар входит в ковбой и требует выпивку — это объявление, декларация намерений.
Бармен спрашивает — чем будешь платить: деньгами, отдашь пистолет или отработаешь мытьем посуды? — Я заплачу, — отвечает ковбой, — у меня есть деньги. — Это определение типа данных.
Тогда плати 5 баксов и получай выпивку — Ковбой платит и веселье начинается — Это инициализация, присвоение начального значения, запуск процесса в работу.
Заметка
Обратите внимание, что мы используем выражение «тип данных» и по отношению к значению, и по отношению к переменным и константам. Дело в том, что в программировании по большому счета можно практически все называть типом данных. Это и объекты, и классы, и наиболее нам известные Int, String, Double, Bool и т.д.
Но, чтобы как-то все же отличать типы данных значений от констант и переменных будем называть последние некими сущностями, элементами языка программирования. Тогда у нас будут типы данных для значений и типы данных для определенных элементов программирования (к которым относятся в том числе константы и переменные).
Автор: Максим Савостьянов
