Подставляемые inline функции 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Подставляемые inline функции



Некоторые функции в языке Си++ можно определить с использованием специального служебного слова inline. Спецификатор inline позволяет определить функцию как встраиваемую или подставляемую, или "инлайн-функцию. Например, следующая функция определена как подставляемая,

inline float module (float x = 0, float у = 0) {

return sqrt (x*x + у*у);

}

Функция module () возвращает значение типа float. Обрабатывая каждый вызов встраиваемой функции, компилятор "пытается" подставить в текст программы код операторов ее тела. Спецификатор inline в общем случае не влияет на ре­зультаты вызова функции, она имеет обычный синтаксис определения и описания, подчиняется всем правилам контроля типов и области действия. Однако вместо команд передачи управления единственному экземпляру тела функции компилятор в каждое место вызова функции помещает соответствующим образом настроенные команды кода опе­раторов тела функции. Тем самым при многократных вызовах под­ставляемой функции размеры программы могут увеличиться, однако исключаются затраты на передачи управления к вызываемой функции и возвраты из нее. Кроме эко­номии времени при выполнении программы, подстановка функции позволяет проводить оптимизацию ее кода.

Наиболее эффективно использовать подставляемые функции в тех случаях, когда тело функции состоит всего из нескольких операторов. Идеальными претендентами на определение со спецификатором inline являются несложные короткие функции. Удобны для подстановки функции, основное назначение которых - вызов других функций либо выполнение преобразований типов.Так как компилятор встраивает код подставляемой функции вмес­то ее вызова, то определение функции со спецификатором inline долж­но находиться в том же модуле, что и обращение к ней, и размещается до первого вызова.

Следующий случай, когда подстановка для функции со спецификатором inline проблематична, - вызов этой функции с помощью указателя на нее. Реализация такого вызова, как правило, будет выполняться с помощью стандартного механизма обращения к функции.

Причины, по которым функция со спецификатором inline будет трактоваться как обыч- ная функция (не подставляемая):

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

· встраиваемая функция рекурсивна;

· обращение к встраиваемой функции в программе размещено лл ее определения;

· встраиваемая функция вызывается более одного раза в выраже­нии;

· встраиваемая функция содержит цикл, переключатель или опе­ратор перехода

Если же для функции со спецификатором inline компилятор не может выполнить подстановку из-за контекста, в который помещено обращение к ней, то функция считается статической (static) и выдается предупреждающее сообщение.

# include <iostream. h>

inline int even(int x) {

return! (x%2)

};

int main() {

int n;

cin» n;

if (even(n))

cout «n «" является четным \n ";

else

cout «n «" является нечетным \n";

return 0;

}В этом примере программа читает введенное целое число и сообщает, является ли оно четным. Функция even () объявлена как встраиваемая. Это означает, что оператор

if (even(n)) cout «n «"является четным\n";

эквивалентен следующему:

if (!(n%2))

cout «n «"является четным\n";

 

На рисунке показаны 4 способа объявления функций в языке программирования С++. Рассмотрим структуры объявления функций в одном файле, с главной функцией. Функции можно объявлять в двух областях, до начала функции main(), после функции main(). До сих пор мы объявляли функции в одном файле, перед функцией main() — это самый простой из способов.

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 // struct_func.cpp: определяет точку входа для консольного приложения.   #include "stdafx.h" /*область 1 - объявление функций до начала main()   место для объявления функций функциям объявленным в этой области не нужны прототипы   */ int main(int argc, char* argv[]) {   return 0; }

 

Если функции объявлять в области 1, перед главной функцией, то прототипы для этих функций не нужны. Хорошему стилю программирования соответствует способ объявления функций после main(). Рассмотрим структуру такого объявления функций.

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // struct_func.cpp: определяет точку входа для консольного приложения.   #include "stdafx.h"   // место для объявления прототипов функций   int main(int argc, char* argv[]) {   return 0; }   /*область 2 - объявление функций после main()   место для объявления функций   */

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

 

1 2 // синтаксис объявления прототипа /*тип возвращаемых данных функции*/ /*имя функции*/(/*параметры функции*/);

 

Структура объявления прототипа очень схожа со структурой объявления функции. Разработаем программу, которая определяет, является ли введённое пятизначное число палиндромом. Палиндром — это число или текст, который читается одинаково как слева, так и справа: 93939; 49094; 11311.

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 // palindrom_func.cpp: определяет точку входа для консольного приложения.   #include "stdafx.h" #include <iostream> using namespace std;   bool palindrom5(int); // прототип функции нахождения палиндрома пятизначных чисел   int main(int argc, char* argv[]) { cout << "Enter 5zn-e chislo: "; // введите пятизначное число int in_number, out_number; // переменные для хранения введённого пятизначного числа cin >> in_number; out_number = in_number; // в переменную out_number сохраняем введённое число   if (palindrom5(in_number)) // если функция вернёт true, то условие истинно, иначе функция вернёт false - ложно cout << "Number " << out_number << " - palendrom" << endl; else cout<<"This is not palendrom"<<endl; system("pause"); return 0; } bool palindrom5(int number) // функция нахождения палиндрома пятизначных чисел { int balance1, balance2, balance4, balance5; // переменные хранящие промежуточные результаты balance1 = number % 10; // переменной balance1 присвоили первый разряд пятизначного числа number = number / 10; // уменьшаем введённое число на один разряд   balance2 = number % 10; // переменной balance2 присвоили второй разряд number = number / 100; // уменьшаем введённое число на два разряда   balance4 = number % 10; // переменной balance4 присвоили четвёртый разряд number = number / 10; // уменьшаем введённое число на один разряд   balance5 = number % 10; // переменной balance5 присвоили пятый разряд if ((balance1 == balance5) && (balance2 == balance4)) return true; // функция возвращает истинное значение else return false; // функция возвращает ложное значение }

В строке 7 объявлен прототип функции нахождения палиндрома пятизначных чисел. Обратите внимание на то, что прототип полностью должен совпадать с заголовком функции, но некоторые отличия все же есть. Например, то, что в прототипе имена параметров перечислять не надо, достаточно объявить их типы данных. В конце объявления прототипа всегда нужно ставить точку с запятой. В остальном объявление прототипа совпадает с объявлением заголовка одной функции. Прототип необходимо объявлять для каждой функции отдельно. Переменная out_number служит для временного хранения введённого числа. В строке 16 в условии оператора выбора if выполняется запуск функции palindrom5(). Аргументом для неё является переменная in_number. функция вернёт значение типа bool, и если функция вернёт true, то условие будет истинно, в противном случае — ложно. Можно было бы сначала присвоить значение, возвращаемое функцией, некоторой переменной, а потом эту переменную подставить в условие оператора выбора if, но это бы увеличило код программы на одну строку. В строках 23 — 40 объявлена функция palindrom5(), с одним параметром, через который функции передаётся пятизначное число. Переменные balance1, balance2,balance4,balance5 объявлены в строке 25, и необходимы для хранения разрядов пятизначного числа: первого, второго, четвёртого, пятого (нумерация — справа на лево). В строках 26, 29, 32, 35 выполняется одна и та же операция — остаток от деления. Операция остаток от деления отсекает по одному разряду справа налево и сохраняет их в переменные balance1, balance2,balance4,balance5соответственно. Причём операция остаток от деления чередуется с операцией обычного деления. Операция деления выполняется в строках 27, 30, 33, и уменьшает введённое пятизначное число за шаг на один разряд. В строке 30 операция деления уменьшает введённое число сразу на два разряда, потому, что число пятизначное и средний разряд нас не интересует, он может быть любым. В строках 36 — 39 объявлен оператор выбора if, который сравнивает разряды пятизначного числа, и если они, соответствующим образом, равны, то функция вернёт значение true, иначе — false.

До сих пор мы объявляли функции в одном файле, с основной программой, то есть там, где находится функция main(). В С++ существует возможность поместить объявления функций в отдельный файл, тогда необходимо будет подключать файл с функциями, как в случае с подключением стандартных заголовочных файлов. Есть два способа:

  1. создание файла типа *.cpp, в котором объявляются функции;
  2. создание файлов типа *.cpp и *.h.

К хорошему стилю программирования относится второй способ. Таким образом, если объявлять функции в другом файле, то делать это согласно способу два. Переделаем программу нахождения палиндрома так, чтобы объявление функции palindrom5() находилось в отдельном файле *.cpp. Файл *.h нужен для того, чтобы скрыть реализацию функций, т. е. в файле *.h будут содержаться прототипы функций. С помощью обозревателя решений MVS создаём файл типа *.h и называем его palendrom.

 

1 2 3 4 5 // код файла palendrom.h #ifndef palendrom #define palendrom bool palindrom5(int); // прототип функции нахождения палиндрома пятизначных чисел #endif

 

Директивы в строках 2,3,5 необходимо всегда объявлять в файлах с прототипами функций, причём прототипы функций всегда объявляются в файлах типа *.h. После директив записанных в строках 2,3, но до директивы #endif объявляются прототипы функций. В строке 4 объявлен прототип функции palindrom5(). Объявление данной функции находится в файле palendrom.cpp, который предварительно тоже был создан с помощью обозревателя решений MVS.

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // содержимое файла palendrom.cpp #include "stdafx.h" #include "palendrom.h" bool palindrom5(int number) // функция нахождения палиндрома пятизначных чисел { int balance1, balance2, balance4, balance5; // переменные хранящие промежуточные результаты balance1 = number % 10; // переменной balance1 присвоили первый остаток number = number / 10; // уменьшаем введённое число на один разряд   balance2 = number % 10; // переменной balance2 присвоили второй остаток number = number / 100; // уменьшаем введённое число на два разряда   balance4 = number % 10; // переменной balance4 присвоили четвёртый остаток number = number / 10; // уменьшаем введённое число на один разряд   balance5 = number % 10; // переменной balance5 присвоили пятый остаток if ((balance1 == balance5) && (balance2 == balance4)) return true; // функция возвращает истинное значение else return false; // функция возвращает ложное значение }

 

В файле palendrom.cpp находится объявление функции palindrom5(). Так как файл palendrom.cppявляется исполняемым файлом (*.cpp — исполняемые файлы), то в нём обязательно нужно подключить контейнер "stdafx.h", как в строке 2. Чтобы связать файл, где объявлена функция palindrom5() и файл с её прототипом, подключим заголовочный файл (файл с прототипом), это сделано в строке 3. Обратите внимание на то, что при подключении созданного нами файла используются двойные кавычки, а не знаки больше, меньше. Осталось только запустить функцию palindrom5()в главном исполняемом файлеfunc_palendrom.cpp.

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // func_palendrom.cpp: определяет точку входа для консольного приложения.   #include "stdafx.h" #include <iostream> // подключение заголовочного файла, с прототипом функции palindrom5() #include "palendrom.h" using namespace std;   int main(int argc, char* argv[]) { cout << "Enter 5zn-e chislo: "; // введите пятизначное число int in_number, out_number; // переменные для хранения введённого пятизначного числа cin >> in_number; out_number = in_number; // в переменную out_number сохраняем введённое число   if (palindrom5(in_number)) // если функция вернёт true, то условие истинно, иначе функция вернёт false - ложно cout << "Number " << out_number << " - palendrom" << endl; else cout<<"This is not palendrom"<<endl; system("pause"); return 0; }

 

В строке 6 мы подключили файл с прототипом функции palindrom5(), после чего можно использовать эту функцию. Итак, мы разбили программу на три файла:

  • файл проекта: func_palendrom.cpp
  • заголовочный файл palendrom.h
  • исполняемый файл palendrom.cpp

Файл проекта связываем с заголовочным файлом, а заголовочный файл связываем с исполняемым файлом, в таком случае файл проекта увидит функцию palindrom5() и сможет её запустить.

Основные моменты в работе с функциями

1. Функция – это именованная последовательность операторов, выполняющая законченное действие. Функции нужны для упрощения структуры программы.

2. Интерфейс грамотно написанной функции определяется ее заголовком.

3. Для вызова функции надо указать ее имя и набор аргументов.

4. В определении, в объявлении и при вызове функции типы и порядок следования аргументов и параметров должны совпадать.

5. Передача параметров в функцию может выполняться по значению или по адресу.

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

7. При написании функции нужно предусмотреть все возможные ошибки и обеспечить пользователя функции средствами их диагностики.

8. Печать диагностических сообщений внутри функции нежелательна.

9. Функция может иметь несколько параметров со значениями по умолчанию. Они должны находиться в конце списка параметров.

10. Массивы всегда передаются в функцию по адресу. Количество элементов в массиве должно передаваться отдельным параметром.

11. Рекурсивная функция должна содержать хотя бы одну нерекурсивную ветвь. При использовании рекурсии следует учитывать возникающие при этом проблемы и накладные раходы.

12. В многофайловых проектах важно грамотно разбить задачу на подзадачи и распределить функции по файлам.

13. Для предотвращения ошибок компиляции, связанных с повторным включением заголовочных файлов, следует использовать так называемые стражи включения.

Индивидуальные варианты заданий

1. Выполнить задания лабораторной работы №4 (Работа с массивами) в соответствии со своим вариантом, оформив каждый пункт задания в виде функции. Все необходимые данные для функций должны передаваться им в качестве параметров. Использование глобальных переменных в функциях не допускается.

2. Выполнить задания лабораторной работы №5 (Работа со строками) в соответствии со своим вариантом, оформив в виде функций законченные последовательности действий. Все необходимые данные для функций должны передаваться им в качестве параметров. Использование глобальных переменных в функциях не допускается. Функция должна быть описана в отдельном модуле и подключена к основной программе.

 

Контрольные вопросы

1. Как определить функцию?

2. Как обращаться к функции и как установить связи между функцией и программой, ее вызывающей?

3. В чем различие между формальными и фактическими аргументами функции?

4. Где необходимо описывать аргументы функции?

5. Где необходимо описывать другие локальные переменные?

6. Когда и как использовать оператор return()?

7. Когда и как использовать адреса и указатели для доступа к объектам?

8. Понятие рекурсии.

 

Содержание отчета

1. Титульный лист

2. Цели, задачи работы

3. Индивидуальное задание

4. Блок-схема алгоритма (для каждой задачи)

5. Листинг программы(для каждой задачи)

6. Результат выполнения программы – скриншот (для каждой задачи)

7. Ответы на контрольные вопросы

 

Практическая работа №7.Структуры в С++. Словари и списки

Цель работы: изучение создания структур, словарей и списков в С++.

 

Задачи:

1. Изучить теоретический материал

2. Написать программу согласно индивидуальному варианту задания.

3. Ответить на контрольные вопросы.

4. Оформить отчет.

 

Теоретический материал

 

Структуры

Структура — это, некое объединение различных переменных (даже с разными типами данных), которому можно присвоить имя. Например можно объединить данные об объекте Дом: город (в котором дом находится), улица, количество квартир, интернет(проведен или нет) и т.д. в одной структуре. В общем, можно собрать в одну совокупность данные обо всем, что угодно, точнее обо всем, что необходимо конкретному программисту. Всем сразу стало понятно:)

Если вы только приступаете к знакомству со структурами в С++, сначала, вам необходимо ознакомиться с синтаксисом структур в языке С++. Рассмотрим простой пример, который поможет познакомиться со структурами и покажет, как с ними работать. В этой программе мы создадим структуру, создадим объект структуры, заполним значениями элементы структуры (данные об объекте) и выведем эти значения на экран.

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> using namespace std;   struct building //Создаем структуру! { char *owner; //здесь будет храниться имя владельца char *city; //название города int amountRooms; //количество комнат float price; //цена };   int main() { setlocale (LC_ALL, "rus");   building apartment1; //это объект структуры с типом данных, именем структуры, building   apartment1.owner = "Денис"; //заполняем данные о владельце и т.д. apartment1.city = "Симферополь"; apartment1.amountRooms = 5; apartment1.price = 150000;   cout << "Владелец квартиры: " << apartment1.owner << endl; cout << "Квартира находится в городе: " << apartment1.city << endl; cout << "Количество комнат: " << apartment1.amountRooms << endl; cout << "Стоимость: " << apartment1.price << " $" << endl;   return 0; }

 



Поделиться:


Последнее изменение этой страницы: 2021-04-20; просмотров: 81; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.147.36.213 (0.103 с.)