Представьте, что Вам с какой-то периодичностью придется выводить на экран "Hello, World!". Пример надуманный, но для начала нам нужен именно он:
#include <iostream>
int main()
{
std::cout << "Hello, World!" << std::endl;
// ...
if( x > y )
{
std::cout << "Hello, World!" << std::endl;
}
// ...
std::cout << "Hello, World!" << std::endl;
// ...
return 0;
}
}
Эта программа будет работать и все будут довольны до тех пор, пока по каким-то обстоятельствам Вы не решите изменить эту надпись. И вот, решение принято: надпись надо заменить на такую же, но с тремя восклицательными знаками("Hollo, World!!!"). Вам придется отыскать все места в коде, где написано приветствие "Hello, World!" и заняться monkey job(работой для обезьян), дописывая во все приветствия два знака восклицания(я знаю про поиск и замену, но далеко не все участки кода им поддаются).
Есть способы для решения подобных проблем. Но для начала задайтесь вопросом, что является корнем такой проблемы? Может это изменение требований к программе? Уверяю Вас, нет. Требования меняются, это не должно влиять на гибкость и качество нашего кода. Может слишком частое использование одной и той же конструкции в коде? Тоже нет. Проблема здесь в дублировании кода. Один и тот же вывод на экран просто копируется и вставляется в новые участки кода. А если повторяться будет один и тот же цикл или условие, нас ждут проблемы куда больше(помимо самой раздутости кода).
Поэтому, хороший программист создает для повторяющегося кода функцию и в нужном месте вызывает ее. Напишем функцию "printGreeting" для вывода на экран строки "Hello, World!":
#include <iostream>
void printGreeting()
{
std::cout << "Hello, World!" << std::endl;
}
int main()
{
// ...
Код, представленный выше, называется определением функции. То есть, вводом новой, пользовательской операции в дополнение к существующим. Сначала идет тип возвращаемого значения: void. Из глав посвященных типам данных Вы помните о его существовании. Этот тип мы не рассматривали, так как переменную такого типа нельзя объявить. Он служит для указания того, что функция ничего не возвращает(об этом в последующих главах). Далее следует имя функции "printGreeting". А за именем список параметров, заключенный в круглые скобки. Как видите, между круглыми скобками у нас тоже ничего нет. Выходит, мы написали функцию самого примитивного вида: функцию, что ничего не возвращает и не имеет параметров. Код между фигурными скобками называется телом функции(подобно телу цикла или условия).
А теперь вызовем ее во всех местах, где нам нужен вывод приветствия на экран:
#include <iostream>
void printGreeting()
{
std::cout << "Hello, World!" << std::endl;
}
int main()
{
printGreeting();
// ...
if( x > y )
{
printGreeting();
}
// ...
printGreeting();
// ...
return 0;
}
}
Конструкция "printGreeting()" называется вызовом функции. С точки зрения логики, вызов функции работает, как если бы мы вписали тело функции в место ее вызова. Пока Вы старались уследить за множеством новых понятий, решилась проблема дублирования кода. Теперь, как бы часто не менялись требования к выводу приветствия на экран, сделать изменения надо будет лишь в одном месте - в теле функции "printGreeting".
Комментариев нет:
Отправить комментарий