- •Федеральное агентство связи
- •Базовые стандартные типы данных
- •Определение объекта типа функции.
- •Проблема обмена информацией (данными) между функциями.
- •Передача информации в функцию через параметры по значению. Возврат значения одного результата из функции через возвращаемое значение.
- •Прототип (описание) функции. Понятие глобального объекта.
- •Передача параметров по ссылке.
- •Обмен данными между функциями через глобальные объекты.Функции без возвращаемого значения. Функции без параметров.
- •Смешанный обмен данными между функциями
- •Программы, состоящие из двух и более файлов.
- •Void countX (float c, float& X); // описанa функция countX для расширения ее // области видимости. Ее определение
- •Приложение 1
Передача параметров по ссылке.
Итак, мы рассмотрели средства обмена информацией между двумя объектами-функциями такие, в которых вызывающая функция через параметры, передаваемые по значению, может передать в вызываемую функцию одно или много значений, а вот получить от этой функции в качестве результата ее работы может только одно значение: через возвращаемое значение.
А если результатов работы вызываемой функции больше чем одно?
В этом случае можно воспользоваться параметрами, передаваемыми по ссылке. Параметры по ссылке указываются в списке формальных параметров как и параметры, передаваемые по значению, через запятую, и их может быть указано столько, сколько надо вернуть результатов - много.
Что же это за параметры? Для этого изучим новый производный тип – ссылка на тип
Имя типа«ссылка на тип»составляется из имени_типа и символа'&', например:
int& float& char&
Говорят «ссылка на int», «ссылка на float», «ссылка на char».
Этот тип определяет не новый объект, а новое альтернативное имя уже существующего объекта. Этот тип не создает новый объект, а уже созданному объекту дает второе имя.
Сначала всегда определяется объект нужного типа и только после этого можно создать ссылку на этот же тип (ссылка не может изменить тип именуемого объекта) и инициализировать его именем объекта, которому ссылка задает второе имя. Ссылка всегда должна бытьинициализирована!
Создадим следующие объекты инструкциями их определения:
int a = 3, b = 4;
float f;
char s1,s2;
Объектам a,f, иs2определены (даны) новые имена в следующих инструкциях:
int& aNew = a;
float& F = f;
char& ss2 = s2;
Теперь к этим объектам можно обратиться по любому из двух имен. Обращения будут равносильны.
aNew = b; f = 1.77; F = f - 1; ss2 = ‘w‘; s1 = s2;
Так использовать ссылки – экзотика. Да и зачем? Свойства и возможности ссылок на тип чаще всего используют в списке формальных параметров функции для организации обмена данными.
Рассмотрим задачу – пример 2, сделав другую реализацию уже рассмотренной задачи.
Составить функцию countX, которая, получива, b ис через параметры по значению, вычисляетхи возвращает результат его вычисления через параметр по ссылке (откажемся от уже рассмотренной возможности возвращать результат через возвращаемое значение).
В функции mainввести значенияa, , . Используя функциюcountX, вычислить значениеXи выдать на экран.
В функции main не использовать стандартные математические функции.
Для того, чтобы вычислить требуемый результат, функция countXдолжнаполучить с по значению три параметраа, b ис, тип каждого значения float. В этой реализации функция результат вернет не через возвращаемое значение, тип которого теперь void. В списке ее формальных параметров появляется параметр x, тип которого float&.
Имя х в списке формальных параметров определит второе имя того объекта, который получит функция при своем вызове, и которым он будет именоваться в этой функции.
float а
float b void
float c
float& x
Заголовок функции countX, реализуемой в таком виде, должен быть таким:
float countX (float a, float b, float c, float& x )
// файл example3.cpp
#define _USE_MATH_DEFINES
#include <math.h>
#include <iostream>
#include <conio.h>
using namespace std;
void countX (float a, float b, float c, float& x )
{
x= (a * cos(b + c) - b * sin(a + c)) / (pow(a,3) + b * b);
// return x; нет этой инструкции, ведь функция так ничего не вернет!
}
void main ( void )
{
cout<<endl<<"vvedite a, x1, x2 ";
float x1, a, x2;
cin>>a>>x1>>x2;
float vir1;
countX (x1*x1, x2,pi, M_PI_2);
float vir2;
countX(x2, x1 + 1.2, 0, vir2);
float x=1/11. + a * vir1 + 1 / vir2;
cout<< endl <<"X = "<<x;
getch();
}
Пояснения к работе программы в этом варианте.
Программа начинает работать с функции main.
Попрежнему первая исполняемая инструкция-выражение
сout << endl << "vvedite a, x1, x2 ";
выводит на экран подсказку.
Следующая инструкция-выражение вводит информацию с клавиатуры в три объекта a, x1, x2. Пользователь ввел a равное 1, x1 равное 2, x2 равное 3.
В инструкции-выражении
countX ( x1*x1, x2, M_PI_2, vir1);
выполняется оператор ( ) вызова функции, где четвертым параметром, получаемым по ссылке на float, указан объект vir1.
При вызове функции countX эта функция принимает первый фактический параметр по значению ( получает результат вычисления выраженияx1*x1, равное4) и для хранения этого значения4в объекте–функцииcountX создается локальный объект с именема, тип которогоfloat(т.к. первый формальный параметр в списке формальных параметров функцииfloat a). Полученное через параметр значение 4 записывается в этот локальный объект а. Так же передаются остальные два фактических параметра – значения 3 из объекта x2 и 1.57 из константы M_PI_2. Для записи этих значений создаются локальные объекты b и c. Здесь механизм тот, который уже был расмотрен. Значения, записанные в локальные объекты а,b и c используются при вычислении значения выражения (a * cos(b + c) - b * sin(a + c)) / (pow(a,3) + b * b), а полученный результат, равный 0.02, записывается в объект, имя которого х. А имя х при этом первом вызове функции именует объект vir1,так как в списке формальных параметров при вызове была сделана инициализация 4 параметра:
float& x = vir1, то есть имя х в этой фукции назначено новым именем объекта vir1.
Этот объект определен в функции main, следовательно информация вычисленная в функции countX инструкцией
x = (a * cos(b + c) - b * sin(a + c)) / (pow(a,3) + b * b);
ее оператором присвоить записывается в объект с именем х, которое именует объектvir1. Информация из области функцииcountX попадает в область другой функции- функцииmain.
При втором вызове функции countX в инструкции-выражении
countX( x2, x1 + 1.2, 0, vir2);
выполняется оператор () вызова функции countX, где четвертым параметром, получаемым по ссылке на float, указан объект vir2.
Значения, полученные в локальные объекты а,b и c при этои вызове используются при вычислении значения выражения (a * cos(b + c) - b * sin(a + c)) / (pow(a,3) + b * b), а полученный результат, равный теперь -0.09, записывается в объект, имя которого в этой функции попрежнему х. А это имя при этом новом вызове функции именует объект vir2,так как в списке формальных параметров при этом вызове была сделана инициализация 4 параметра:
float& x = vir2, то есть имя х в этой фукции будет новым именем объекта vir2.
Этот объект попрежнему определен в функции main. Таким образом информация вычисляется функцией countX в инструкции
x = (a * cos(b + c) - b * sin(a + c)) / (pow(a,3) + b * b);
Оператором присвоить эта инструкция записывает результат в область памяти другой функции, в область памяти объекта vir2.
(Технически такой механизм передачи объекта по ссылке использует все тот же механизм передачи через параметры по значению адреса передаваемого объекта, например, vir1. Но к полученному по значению адресу объекта vir1, автоматически применяется оператор взятия объекта и таким образом, обеспечивается работа не с переданным адресом объекта, а с самим объектом, определенным в другой функции).
По ссылке можно передать объект, тип которого обязательно должен совпадать с типом, на который сделана ссылка.
// файл example3.cpp
#define _USE_MATH_DEFINES
#include <math.h>
void countX (float a, float b, float c, float& x )
{
x= (a * cos(b + c) - b * sin(a + c)) / (pow(a,3) + b * b);
}
void main ( void )
{
cout<<endl<<"vvedite a, x1, x2 ";
float x1, a;
double x2; // изменен тип объекта на double
// вызывает сообщение-предупреждение Warning 3 warning C4244
cin>>a>>x1>>x2;
double vir1; // изменен тип объекта на double
// вызывает предупреждение о грубой ошибке Error 2 error C2664
countX (x1*x1, x2, M_PI_2, vir1); // строка 22, на которую указано
float vir2;
countX(x2, x1 + 1.2, 0, vir2);
float x = 1./11 + a * vir1 + 1 / vir2;
cout<< endl <<"X = "<<x;
getch();
}
При компиляции этого варианта выдается сообщение об ошибках.
Сообщение в окне List Error
Error 2 error C2664: 'countX' : cannot convert parameter 4 from 'double' to 'float&'пример3\example3.cpp 22
Warning 3 warning C4244: 'argument': conversion from 'double' to 'float', possible loss of data пример3\example3.cpp 22