1. Структура программы на языках С и С++.
Функции С и С++. Перегрузка функций в С++. Ссылки.
Last updated
Функции С и С++. Перегрузка функций в С++. Ссылки.
Last updated
Программа на Си - набор файлов, включающий директивы препроцессора, объявления переменных. Один из файлов должен содержать функцию с именем main
(но не обязательно, программа может начинаться с любой другой функции). Иными словами, программа на языке Си является набор подпрограмм (функций), внешних по отношению друг к другу (по стандарту).
Любая функция может вызвать любую другую, в том числе вызвать саму себя.
Исключением является функция main()
- в С++ функция main()
саму себя вызвать не может. При выполнении консольного приложения, написанного на языке Си, операционная система компьютера передаёт управление функции с именем main()
. Функцию main()
нельзя вызывать из других функций программы, она является управляющей.
Объявления необходимы компилятору. Объявлять можно один раз, определять - сколько угодно. Компилятор подставляет константы.
В С и С++ каждый файл компилируется раздельно, либо с помощью makefile.
Получение исполняемого файла *.exe
:
Препроцессирование - удаление комментариев, замена #define, подключение заголовочных файлов *.h
(путем копирования содержимого). Для избежания повторного копирования используется #pragma once или #ifndef G_H
.
Компиляция - перевод написанного на языке C++ кода в код ассемблера.
Ассемблирование - перевод из кода ассемблера в машинный код. Получаем объектный файл с расширением *.obj
.
Компоновка/линковка - объединение объектных файлов в один исполняемый *.exe
.
Пример многофайловой программы:
#pragma once
исключает множественное включение файлов.
Заголовочные файлы - описание типов, констант, библиотеки, функций, логически вынесенных в другой исходный файл.
Что можно, а что нельзя определять в заголовочном файле:
Определять переменные нельзя. Мы конечно можем это сделать, и на этапе компиляции проблем не будет, но сборщик покажет множественное определение - ошибочка.
То же самое касается функций. В заголовочном файле описываются только прототипы функций.
К языковой константе компилятор относится как к макросу, поэтому в заголовочном можно определять константу.
Аналогично с типами - типы тоже можно определять в заголовочном файле.
То есть все константы и типы выносим в заголовочный, а так же прототипы функций.
С такими константами компилятор вычисляет ее, и подставляет в код вместо вызова.
Определяем константы в том случае, если она вычислима на этапе компиляции - Константа времени компиляции, а те константы которые не могут быть вычислены на этапе компиляции, а вычисляются во время выполнения, то это Константа времени выполнения нельзя определять в заголовочном файле
В языке С структурное соответствие типов, то есть typedef
это определение еще одного имени, один и тот же тип может иметь много имен, проверяется не имя типа, а его структура.
В языки С++ именное соответствие типов, две одинаковые структуры, имеющие разные имена являются разными типами.
Подключать g.h на уровне f.h файлов нельзя, приводит к лавинное перекомпиляции, на время разработки мы их комментируем. В случае релиз версии тогда, все g.h включения идут в f.h файл, а в f.cpp .h комментируем.
f.h и f.cpp рассматривается как модуль и многие среды создают такие пары.
Структуру по значению передавать плохо, так как происходит копирование в стек, а это занимает время. Лучше по ссылке или указателю. Но у указателей есть проблема - контроль (сложно проверить корректность, только на NULL
).
Ссылка (alias)
- ещё одно имя того же самого данного. Ссылка - не тип данных!
Ссылки используются для передачи параметра в функцию. На низком уровне ссылки хоть ничем не отличается от указателя, но идет контроль!
О возврате. Нельзя возвращать ссылку на локальную переменную. Возврат по ссылке нужен для формирования левого выражения =
, чтобы присвоить переменной нужное значение.
В С++
можно создавать разные функции с одинаковыми именами, у которых параметры разного типа или их разное количество - использовать перегрузку функций.
Теряется такой механизм неявное приведение типа - а это ХОРОШО
В С++ о неявном будем говорит, так как создатель добавил возможность задавать свои механизмы неявного типа - но это ПЛОХО, пишем код для врагов.
На перегрузку функции влияет:
Разное количество принимаемых параметров.
Разный тип переменных.
const значение функции/метода. Если объект константный, то будет вызываться const метод, иначе не const.
Примечание о том, что значит модификатор const у метода. Константный метод - это метод, который гарантирует, что не будет изменять объект или вызывать неконстантные методы класса (поскольку они могут изменить объект). Соответственно, для константных объектов нельзя вызывать неконстантные методы.
Тип возвращаемой переменной не имеет значение.