Сдам Сам

ПОЛЕЗНОЕ


КАТЕГОРИИ







Константные аргументы функции





Как мы уже знаем, при передаче аргумента по значению, мы не можем изменить переменную из вызывающего окружения. Если мы всё же хотим изменить значение этой переменной, то аргумент нужно передавать по ссылке. Но иногда возникает ситуация, когда нужно передать аргумент по ссылке и при этом запретить его изменять. Для этого можно воспользоваться константными аргументами функции. В списке аргументов объявления/определения нужно поставить ключевое слово const перед соответствующим аргументом:

int simple_function(const int&, int);

 

int simple_function(const int& a, int b);

{

a = 1; // Компилятор выдаст ошибку! Нельзя изменять переменную a

return 0;

}

Теперь, для чего это нужно: в следующих уроках мы познакомимся с новыми типами данных. Эти типы данных в некоторых случаях могут занимать сотни байт (сравните со стандартным типом double - 8 байт). Если передавать эти аргументы в функцию по значению, то будет происходить копирование, а это значит замедление программы. Поэтому для большей эффективности мы будем передавать эти переменные по ссылкам. Ну а чтобы "случайно" не изменить их значения, будем пользоваться константными аргументами.

Встраиваемые функции (inline functions)

Вызов функции, передача в неё значений, возврат значения, эти операции занимают довольно много процессорного времени. Когда мы будем рассматривать более реальные примеры, у нас будут функции в один-два оператора (в основном - математические), которые нужно будет выполнять тысячи раз в секунду. Так как размер функции небольшой (несколько операторов), то время выполнения тела функции будет меньше чем процесс вызова/передачи аргументов/возврата значения. Чтобы сократить время работы программы, можно воспользоваться встроенными функциями.

Перед объявлением/определением функции нужно добавить ключевое слово inline.

При этом, во время компиляции все вызовы функции будут заменены непосредственно кодом функции. При этом программа будет выполняться быстрее, но займёт больше памяти (если функция вызывается много раз):

inline void simple_function()

{

// тело функции

}

 

int main ()

{

simple_function();

simple_function();

simple_function();

return 0;

}

Во время компиляции этот код превратится в следующий:

int main ()

{

// тело функции

// тело функции

// тело функции

return 0;

}

Компилятор решает делать функцию встраиваемой или нет, в зависимости от размера функции. Т.е. если вы пытаетесь сделать длинную функцию (в которой, например, сотня операторов) встраиваемой, то компилятор сочтёт её слишком большой, и будет её использовать как обычную.

Библиотечные функции

Практически с первого урока мы уже использовали функции:

_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 и нужно закончить выполнение программы.

Заключение

Урок по функциям получился очень большим, вам понадобится время чтобы всё понять и осмыслить.

Самое важное, что нужно усвоить в самом начале: функция - это всего-лишь группа операторов у которой есть имя.

Функции используются в двух основных случаях:
1. Если операторы, составляющие тело функции, встречаются в программе много раз. Тогда имеет смысл создать для них отдельную функцию. При этом произойдёт сокращение кода.
2. Для организации кода, если несколько операторов программы выполняют какую-то конкретную задачу. При этом размер кода может и не уменьшится, но программа станет более читабельной.

Посмотрим вот на такой пример:

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, статические переменные - это дополнительные возможности. Да, они чрезвычайно важны, но всё-таки, это дополнительные возможности.

 







Что делает отдел по эксплуатации и сопровождению ИС? Отвечает за сохранность данных (расписания копирования, копирование и пр.)...

Система охраняемых территорий в США Изучение особо охраняемых природных территорий(ООПТ) США представляет особый интерес по многим причинам...

Что делать, если нет взаимности? А теперь спустимся с небес на землю. Приземлились? Продолжаем разговор...

Конфликты в семейной жизни. Как это изменить? Редкий брак и взаимоотношения существуют без конфликтов и напряженности. Через это проходят все...





Не нашли то, что искали? Воспользуйтесь поиском гугл на сайте:


©2015- 2024 zdamsam.ru Размещенные материалы защищены законодательством РФ.