Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информатика_УчебноеПособие.doc
Скачиваний:
44
Добавлен:
03.05.2015
Размер:
862.21 Кб
Скачать

Передача параметров по ссылке.

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

А если результатов работы вызываемой функции больше чем одно?

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

Что же это за параметры? Для этого изучим новый производный тип – ссылка на тип

Имя типа«ссылка на тип»составляется из имени_типа и символа'&', например:

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