|
Идентификатор или имя функцииСтр 1 из 3Следующая ⇒ Определение функции Определение функции должно располагаться в глобальной области видимости, до начала функции main. Рассмотрим пример, простого определения: int simple_function () { return 0; } Определение функции состоит из заголовка и тела. Заголовок фукнции включает в себя: Тип возвращаемого значения Почти все функции должны возвращать значения. Тип этого значения указывается в заголовке перед именем функции. Вот несколько примеров заголовков функций: int simple_function() float simple_function() char simple_function() В первом случае функция должна вернуть целое число (int), во втором - вещественное число (float), а в третьем случае - символ (char). Возвращаемые значения используются для передачи данных из функции в вызывающее окружение. Вызывающее окружение - это то место, откуда вызывается данная функция, подробнее ниже. Идентификатор или имя функции Идентификатор (имя) функции задаётся точно также, как и любой другой идентификатор. В данном примере мы создали функцию с идентификатором simple_function (simple - простой). Список аргументов или параметров Список аргументов функции записывается в круглых скобках после имени функции. В данном примере список аргументов пуст. Список аргументов записывается через запятую. Каждый элемент списка состоит из типа и идентификатора. Рассмотрим пример заголовка функции со списком из двух аргументов: int simple (int a, float b) В скобках мы записали два аргумента: a и b. У аргумента a тип int, а у аргумента b тип float. Аргументы используются, когда в функцию нужно передать какие-либо данные из вызывающего окружения. Тело функции Тело функции располагается сразу под заголовком и заключено в фигурные скобки. В теле функции может содержаться сколько угодно операторов. Но обязательно должен присутствовать оператор return. Оператор return возвращает значение: int simple_function () { return 0; } Здесь, simple_function всегда будет возвращать 0. Надо признать, что данная функция бесполезна. Напишем функцию, которая принимает из вызывающего окружения два значения, складывает их и возвращает результат в вызывающее окружение. Назовём эту функцию sum (сумма): int sum (int a, int b) { int c; c = a + b; return c; } В функцию передаётся два аргумента: a и b типа int. В теле функции они используются как обычные переменные (они и являются обычными переменными). Давайте договоримся: снаружи функции, переменные, которые передаются в неё, мы будем называть аргументами, а эти же переменные в теле функции - параметрами. В теле функции определяется переменная c. А затем, в эту переменную мы помещаем значение суммы двух параметров. Последняя строчка возвращает значение переменной c во внешнее окружение. После ключевого слова return нужно указать значение которое будет возвращено. Можно возвращать как простые значения, так и переменные и даже выражения. Например: return 32; return a; return b; return a+b; В последнем случае в вызывающее окружение будет возвращён результат суммы переменных a и b. Обратите внимание, что оператор return не только возвращает значение, но и служит как бы выходом из функции, после него не будет выполнен ни один оператор: return a; c = a+b; // этот оператор не будет выполнен Благодаря этому, с помощью return удобно создавать условия выхода из функций: if (a > 0) { return 0; } else if (a < 0) { return 1 } Здесь, из функции будет возвращено число в зависимости от значения переменной a: если a больше нуля, то будет возвращён 0, в противном случае - 1. Вызов функции После того как создано определение функции, её можно вызвать. int sum (int a, int b) { int c; c = a + b; return c; }
int main() { int s; s = sum(2,2); // вызов функции cout << s; return 0; } В результате выполнения программы, на экран будет выведено: 4. Вызов функции состоит из идентификатора функции и списка аргументов в круглых скобках. Вот несколько вызовов функции sum: int x = 5; int y = 4; int z;
sum(0,1); // 1 sum(x,2); // 7 sum(x,y); // 9 z = sum(x,y); // z = 9 Вызывающее окружение То место, откуда вызывается функция, называется вызывающим окружением. Вызывающим окружением функции sum является функция main, а вызывающим окружением функции main является отладчик или операционная система. Функция может обмениваться данными с вызывающим окружением благодаря списку аргументов и возвращаемому значению: вызывающее окружение передаёт данные в функцию с помощью аргументов, а функция передаёт данные в вызывающее окружение с помощью возвращаемого значения. Тип передаваемого в функцию значения должен совпадать с типом указанным в списке аргументов. Нельзя, например, написать вот так: int simple (int a) { return 1; }
int main () { int b; b = simple(0.5); return 0; } В списке аргументов мы указали тип int, а в функцию передаётся вещественное значение 0.5. Так делать нельзя. Рассмотрим более полезный пример: напишем функцию для передвижения персонажа: int x; // глобальная переменная
int move_x (int dx) { x = x + dx; return x; }
int main () { int ch; char act;
while (1) { act = _getch(); ch = static_cast(act);
if (ch == 75) // была нажата стрелочка влево move_x(-1); else if (ch == 77) // была нажата стрелочка вправо move_x(1); } // конец while return 0; } // конец main Обратите внимание, что для тела if и else if не стоит скобочек. Скобочки ветвлений можно опускать, если в теле ветвления всего один оператор. Функция move_x двигает персонажа на одну единицу влево или вправо в зависимости от клавиши, которую нажал пользователь. Создадим ещё одну функцию, а заодно уберём из main часть кода: int x; // глобальная переменная
int move_x (int dx) { x = x + dx; return x; }
void move (int ch) { if (ch == 75) // была нажата стрелочка влево move_x(-1); else if (ch == 77) // была нажата стрелочка вправо move_x(1); }
int main () { int ch; char act;
while (1) { act = _getch(); ch = static_cast(act); move(ch); // вызов функции move } // конец while return 0; } // конец main Обратите внимание, что в функции move на месте типа возвращаемого значения стоит void, кроме того, в теле move нет оператора return. Возврат void На месте возвращаемого типа, в определении (и в объявлении) функции move стоит ключевое слово void (void - пусто, пустой). Это значит, что функция не возвращает никакого значения. Следовательно не требуется и оператор return, так как функции нечего вернуть в вызывающее окружение. Передача массивов в функцию Передача массивов в функцию имеет небольшое отличие от передачи простой переменной. В прототипе функции необходимо указывать идентификатор: int simple_function (int array[]); int simple_function (int array[]) { return 0;} Обратите внимание, что рядом с идентификатором и в объявлении и в определении стоят скобочки. При вызове функции, в которую нужно передать массив, указывается только идентификатор массива (без квадратных скобок): int a[] = { 0, 1, 2 }; simple_function(a); Запомните, при вызове указывается только идентификатор, а при объявлении/определении ещё и скобки. Глобальные переменные Глобальные переменные - это переменные, которые определены за пределами любой функции: int x = 0; // глобальная переменная
int main () { код main }
void simple_function () { x = 5; } Здесь переменная x видна из любой функции программы, в том числе и из simple_function. Что значит: "функция видит переменную"? Это значит, что внутри функции можно обращаться к этой переменной. Глобальные переменные существуют с того момента как они встретились в коде и до конца программы. Т.е. если глобальную переменную объявить после какой-нибудь функции, то в этой функции данную переменную нельзя будет использовать: int main () { код main }
void simple_function () { x = 5 // компилятор выдаст ошибку, переменная ещё не объявлена }
int x = 5; // объявление глобальной переменной
int getX () { return x; // getx видит переменную x } Переменная x объявлена после функций main и simple_function, а значит, в этих функциях её не видно. Локальные переменные Локальные переменные объявлены внутри функций и видны только в них самих: void f1 () { int a; // объявление переменной f2(); }
void f2 () { a = 3; // ошибка, отсутствует объявление переменной } У каждой функции есть своя область видимости. В область видимости функции входят все глобальные переменные и переменные объявленные в этой функции. Механизм передачи значений через аргументы и return предназначен как раз для локальных переменных: int x; // глобальная переменная
void f1 () { int a = 5; int b = 3; int t = 1; x = 5; int c = f2(b,a); }
int f2(int a, int t) { int b = 1; return a+t+x; } Обе функции видят переменную x, т.к. она глобальная. У каждой функции свои переменные a,b,t. У f1 a=5,b=3,t=1, а у f2 a=3,t=5,b=1. Несмотря на то, что у этих функций есть переменные с одинаковыми идентификаторами, это всё-таки совершенно разные переменные. Будьте бдительны! Переменной c будет присвоено значение 13. Перегруженные функции Очень часто возникает ситуация, когда несколько функций выполняют одинаковые действия, только над разными типами. В данном случае можно использовать перегруженные функции. Перегруженные функции - это функции с одним именем, но с разными типами аргументов: int simple_function (float a, float b); int simple_function (int a, int b); int simple_function (int a); Здесь представлено три объявления перегруженной функции simple_function. Для каждого варианта функции, нужно написать своё определение. Перегруженные функции могут отличаться не только типами аргументов, но и их количевством (сравните 2-е и 3-е объявления). И ещё один важный момент: в перегруженных функциях учитываются только аргументы, возвращаемое значение не играет никакой роли. В следующем примере, компилятор выдаст ошибку: int simple_function (int a); float simple_function (int a); Библиотечные функции Практически с первого урока мы уже использовали функции: _getch(); setlocale(LC_CTYPE,"Russian"); Эти функции называются библиотечными. Их объявления находятся в заголовочных файлах, которые мы включаем в наши исходники с помощью #include. Определения этих функций расположены в библиотечных файлах с расширением.lib. Заголовочные файлы расположены в папке studio\VC\include, а библиотечные в studio\VC\lib (studio - папка, куда вы установили Visual Studio C++ 2008). Посмотрите на содержимое заголовочных файлов: conio.h и iostream. Программа pseudo_game_0_3 Прежде чем продолжить, откройте в IDE листинг программы pseudo_game_0_2. Хотя, конечно, лучше бы было, если бы вы самостоятельно написали ту программу. Во время чтения вносите изменения в листинг. Для программы мы напишем две функции: game_init будет инициализировать массив map, а movement_if будет отвечать за передвижение игрока (if ознчает, что в функции будет применяться ветвление if). Объявление функций Сразу после директивы using namespace добавьте определение двух констант: s (от strings - строки), c (от columns - столбцы) - это количество строк и столбцов в массиве. Инициализируйте их значениями 15 и 20. Перед определением main нужно добавить объявления пользовательских функций game_init, movement_if: using namespace std;
const int s = 15; const int c = 20;
int game_init(char map[s][c]); int movement_if(int&, int&,char map[s][c]);
int main() В game_init() передаётся массив map, а в movement_if - два аргумента по ссылке и массив. Определение функций int game_init(char map[s][c]) { for (int i = 0; i < s; i++) { for (int j = 0; j < c; j++) { map[i][j] = ' '; } } map[0][0] = 'Т'; return 0; } В данную функцию мы вынесли инициализацию массива. Обратите внимание, что счётчики сравниваются с константами s и c. Вместо s и c, мы могли бы использовать конкретные числа, но с помощью данных переменных можно в любой момент времени изменить размер игрового поля, изменив только два числа. Теперь рассмотрим функцию movement_if. Переменные ch и act мы поместим в новую функцию, они больше нигде не используются. Также в функции будет подсчитываться сколько ходов сделал игрок. int movement_if (int& x, int& y, char map[s][c]) { char act; int ch; static int counter = 0; int e = 0;
act = _getch(); ch = static_cast(act);
if (ch == -32) {} else if (ch == 27) e = 1; // мы больше не можем использовать break else { // здесь мы можем закодировать ещё какое-нибудь значение e }
return e; } Здесь я убрал код проверки нажатия стрелочек. Для краткости. Функция возвращает значение целого типа, а именно переменную e. Раньше для выхода из программы мы использовали переменную break. Сейчас мы не можем её использовать, так как произойдёт всего-лишь выход из функции movement_if. Вместо этого мы используем переменную e (от error - ошибка), в которую мы сохраняем коды ошибок. 0 - всё в порядке, продолжается выполение программы. 1 - нажата клавиша Esc. Мы можем продолжить, заполнив блок else: 2 - нажата неверная клавиша и закодировав какое-либо действие. Возврашаемое значение присваивается переменной с таким же именем. Кстати, имена этих переменных могли бы быть разными т.к. они обе локальные и никак не связаны друг с другом. Ну и обратите внимание на параметры функции. Мы используем ссылки на x, y для хранения координат и массив. Статическая переменная counter подсчитывает количество ходов. Добавьте инкремент переменной counter в каждый блок, где проверяется нажатие стрелочек. Вызов функции movement_if() осуществляется очень просто: e = movement_if(x,y,map); if (e == 1) break; Переменной e присваивается возвращаемое функцией значение, затем проверяется код ошибки. Если 1, значит была нажата клавиша Esc и нужно закончить выполнение программы. Заключение Урок по функциям получился очень большим, вам понадобится время чтобы всё понять и осмыслить. Самое важное, что нужно усвоить в самом начале: функция - это всего-лишь группа операторов у которой есть имя. Функции используются в двух основных случаях: Посмотрим вот на такой пример: void simple_function () { оператор 1; оператор 2; оператор 3; оператор 4; } int main () { simple_function(); // вызов функции. // другие операторы simple_function(); // вызов функции. return 0; } Без simple_function программа будет выглядеть вот так: int main () { оператор 1; оператор 2; оператор 3; оператор 4; // другие операторы оператор 1; оператор 2; оператор 3; оператор 4; return 0; } Этот код - это так сказать сущность функций.:) Всё остальное: возвращаемое значение, список аргументов, передача по ссылке, оператор return, статические переменные - это дополнительные возможности. Да, они чрезвычайно важны, но всё-таки, это дополнительные возможности.
Определение функции Определение функции должно располагаться в глобальной области видимости, до начала функции main. Рассмотрим пример, простого определения: int simple_function () { return 0; } Определение функции состоит из заголовка и тела. Заголовок фукнции включает в себя: Тип возвращаемого значения Почти все функции должны возвращать значения. Тип этого значения указывается в заголовке перед именем функции. Вот несколько примеров заголовков функций: int simple_function() float simple_function() char simple_function() В первом случае функция должна вернуть целое число (int), во втором - вещественное число (float), а в третьем случае - символ (char). Возвращаемые значения используются для передачи данных из функции в вызывающее окружение. Вызывающее окружение - это то место, откуда вызывается данная функция, подробнее ниже. Идентификатор или имя функции Идентификатор (имя) функции задаётся точно также, как и любой другой идентификатор. В данном примере мы создали функцию с идентификатором simple_function (simple - простой). Что делать, если нет взаимности? А теперь спустимся с небес на землю. Приземлились? Продолжаем разговор... Что будет с Землей, если ось ее сместится на 6666 км? Что будет с Землей? - задался я вопросом... ЧТО ПРОИСХОДИТ, КОГДА МЫ ССОРИМСЯ Не понимая различий, существующих между мужчинами и женщинами, очень легко довести дело до ссоры... ЧТО И КАК ПИСАЛИ О МОДЕ В ЖУРНАЛАХ НАЧАЛА XX ВЕКА Первый номер журнала «Аполлон» за 1909 г. начинался, по сути, с программного заявления редакции журнала... Не нашли то, что искали? Воспользуйтесь поиском гугл на сайте:
|