Бесплатный курс по C++. Зарегистрируйтесь для отслеживания прогресса →

C++: Прототипы функций

В этом уроке мы познакомимся с прототипами функций. Также узнаем, как их определять и для чего они нужны.

Определение прототипа.

Посмотрим на код:

 #include <iostream>
 #include <string>

 int main() {
   std::cout << GetAbsolutePath("main.cpp", "andrey") << std::endl; 
 }

 std::string GetAbsolutePath(std::string file_name, std::string user_name) {
   return "home/" + usr_home_dir + "/" + file_name;
 }

На первый взгляд программа написана правильно, но при компиляции мы получим ошибку ./main.cpp:5:20: error: use of undeclared identifier GetAbsolutePath.

Причина, по которой эта программа не компилируется, — компилятор последовательно компилирует содержимое исходных файлов. Когда компилятор достигает вызова функции GetAbsolutePath в функции main, он не знает, что такое GetAbsolutePath, потому что мы определили GetAbsolutePath ниже ее вызова.

Теперь посмотрим на такой пример:

 #include <iostream>
 #include <string>

 // прототип
 std::string GetAbsolutePath(std::string, std::string);

 int main() {
   std::cout << GetAbsolutePath("main.cpp", "andrey") << std::endl; 
 }

 // определение
 std::string GetAbsolutePath(std::string file_name, std::string user_name) {
   return "home/" + usr_home_dir + "/" + file_name;
 }

Здесь мы определили прототип функции в верхней части. Теперь программа скомпилируется и будет работать.

Синтаксис прототипов довольно простой и похож на синтаксис определения функций: <ТИП ВОЗВРАЩАЕМОГО ЗНАЧЕНИЯ> <ИМЯ> <КОЛИЧЕСТВО И ТИП АРГУМЕНТОВ>. Поскольку прототип функции является оператором, он должен завершаться точкой с запятой.

Прототип функции не требует предоставления имен переменных-параметров, достаточно списка типов.

## Зачем нужны прототипы.

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

В нашем случае прототип сообщает компилятору, что функция GetAbsolutePath возвращает значение типа std::string и принимает два аргумента такого же типа. Если программа не предоставит эти аргументы, то прототип позволит компилятору перехватить такую ошибку.

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

Прототипы значительно снижают вероятность допущения ошибок. Например, в языке С нет прототипов, и если функция ожидает тип int, а мы передадим в нее double, то могут возникать странные ошибки — потеря точности числа. В C++ же это удастся отловить на этапе компиляции.

Итак, в этом уроке мы познакомились с прототипами функций и узнали, чем они полезны.

Задание

Определите прототип функции GetLength, которая принимает строку и возвращает ее длину.

Упражнение не проходит проверку — что делать? 😶

Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:

  • Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет 🤨

Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.

Мой код отличается от решения учителя 🤔

Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.

В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.

Прочитал урок — ничего не понятно 🙄

Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.

Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.

Полезное


Нашли ошибку? Есть что добавить? Пулреквесты приветствуются https://github.com/hexlet-basics
Если вы столкнулись с трудностями и не знаете, что делать, задайте вопрос в нашем большом и дружном сообществе