Краткие теоретические положения




Цель работы

Повторить возможности по созданию программ в интегрированной среде разработки программ Visual Studio; повторить основные принципы создания программ на языке С++; изучить принципы создания и использования функций в программах на языке С++.

Краткие теоретические положения

Функция - часть программы, имеющая собственное название. Любая программа на С содержит функцию main() или WinMain(), которая является ее входной точкой. Функция main() — это частный случай функции вообще. Функции являются основными “строительными блоками” программы. Определить функцию - значит указать, какие действия и как она должна выполнять. Функцию нельзя вызвать до тех пор, пока она не определена. В общем виде функция определяется таким образом:

Тип Имя_функции(список_параметров)

{

// В фигурных скобках заключено тело функции,

// составленное из отдельных операторов.

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

}

Оператором возврата из функции в точку ее вызова является оператор return. Тип возвращаемого выражения должен совпадать с объявленным типом функции.

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

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

#include <conio.h>

#include <iostream>

using namespace std;

 

//определение вспомогательной функции

float Cub(float f) {return f*f*f;}

 

int main()

{int x,y; // объявляем переменные

 

cin>>x; // вводим х

y=Cub(x); //вызываем функцию для вычисления третьей степени числа х

cout<<"\nx^3 = "<< y;

cout<<"\nx^3 = "<< Cub(x);

getch();

return 0;

}

Создайте новое консольное приложение и проверьте работу приведенного примера.

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

В следующем примере объявим функцию Sum() для вычисления суммы трех чисел. Определение функции поместим после функции main().

#include <conio.h>

#include <iostream>

using namespace std;

 

int Sum(int A, char B, char C); // прототип функции, т.е. объявление

 

int main()

{int x,y,z,S;

cin>>x>>y>>z; // Вводим три числа

S=Sum(x,y,z); // Используем функцию

cout<<"\nSumma "<< x <<"+"<<y<<"+"<<z<<"="<< S;

S=Sum(4,3,-2); // Можно так использовать функцию

cout<<"\nSumma 2 = "<< Sum(4,3,-2); // Так тоже можно вызывать функцию

getch();

return 0;

}

 

// определение функции, то есть указание того, что она должна делать

int Sum(int A, char B, char C)

{ return A+B+C;

}

Создайте новое консольное приложение и проверьте работу приведенного примера.

Функция, которая не возвращает результата, объявляется как void. Например, в следующем примере используется функция hello(), которая выводит на экран приветствие. Так как она не возвращает в основную программу никаких результатов, она объявлена как void:

#include <conio.h>

#include <iostream>

using namespace std;

 

void hello(void)

{cout<<"Hello All\n"; return;}

 

 

int main()

{cout<<"Primer: ";

hello();

getch();

return 0;

}

Значения аргументов функции по умолчанию. В прототипах функций можно задавать значения аргументов, передаваемых по умолчанию. Предположим, составлена функция DrawCircle, которая рисует на экране окружность заданного радиуса с центром в заданной точке. Для этой функции можно использовать такой прототип:

void DrawCircle (int x=100, int y=100, int R=50);

или просто:

void DrawCircle (int=100, int=100, int=50);

хотя так труднее читать программу.

Вызовы этой функции могут быть такими:

DrawCircle ();

Рисуется окружность с центром в точке 100;100 и радиусом 50.

DrawCircle (200);

Центр в точке 200;100, радиус 50.

DrawCircle (200,300);

Центр в точке 200;300, радиус 50.

DrawCircle (200,300,100);

Центр в точке 200;300, радиус 100.

DrawCircle (,, 100);

Это ошибка. Разрешается опускать аргументы только справа.

Следующий прототип был бы ошибочным, так как задавать значения по умолчанию надо “начиная справа”:

DrawCircle (int x, int y=100, int R);

 

Перегруженные функции. В программировании то и дело случается писать функции для схожих действий, выполняемых над различными типами и наборами данных. Пусть, например, функция должна возвращать квадрат своего аргумента. В C/C++ возведение в квадрат целого и числа с плавающей точкой — существенно разные операции. Поэтому придется написать две функции — одну, принимающую целый аргумент и возвращающую целое, и вторую, принимающую тип double и возвращающую также double. В С функции должны иметь уникальные имена. Таким образом, перед программистом встает задача придумывать массу имен для различных функций, выполняющих аналогичные действия. Например, SquareInt() и SquareDbl().

В C++ допускаются перегруженные (overloaded) имена функций, когда функции с одним именем можно, тем не менее, идентифицировать по их списку параметров, контексту, так сказать, в котором имя употребляется.

Рассмотрите следующий примерс вышеупомянутыми квадратами.

#include <conio.h>

#include <iostream>

using namespace std;

 

//Первый вариант функции Sq

int Sq(int arg)

{return arg*arg;}

 

//Второй вариант функции Sq

double Sq(double arg)

{return arg*arg;}

 

int main(void)

{int x = 11;

double y = 3.1416;

printf("%d v kvdrate = %d, %f v kvadrate = %f\n",x,Sq(x),y,Sq(y));

getch();

return 0;

}

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

Перегруженные функции являются, по сути, совершенно различными функциями, идентифицируемыми не только своим именем (оно у них одно и то же), но и списком параметров. Компилятор выполняет кодирование имен, дополняя имя функции кодовой последовательностью символов, кодирующей тип ее параметров. Тем самым формируется уникальное внутреннее имя. Тип возвращаемого значения никак не отражается на кодировании имени. Компилятор сам выбирает, какую из нескольких функций вызвать в каждом конкретном случае. Критерием выбора служит количество и тип аргументов, с которыми функция вызывается. Причем, если не удается найти точного совпадения, то компилятор выбирает ту функцию, при вызове которой наиболее легко выполнять для аргументов преобразование типа. Рассмотрим примерпрограммы с перегруженной функцией print:

 

#include <conio.h>

#include <stdio.h>

#include <iostream>

using namespace std;

 

void print(int i) {printf("%d ", i);}

void print(double x) {printf("%f ", x);}

void print(char* s) {printf("%s ", s);}

 

int main()

{int j=5;

float e=2.7183;

double pi=3.1415926;

print(j); print(e); print(pi);

print("Hello All!");

getch();

return 0;

}

В этом примере определены три варианта функции print: для целого и вещественного аргументов, а также для аргумента-строки.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-11-19 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: