ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 5) онлайн
Передача по ссылке аргументов стандартных типов
Следующий пример, REF, демонстрирует передачу по ссылке обычной переменной.
// ref.cpp
// применение ссылочного механизма передачи аргументов #include <iostream> using namespace std;
int main() {
void intfrac(float, float&, float&); // прототип float number, intpart, fracpart; do {
cout << "\nВведите вещественное число:";
cin >> number; // ввод числа пользователем
intfrac(number, intpart, fracpart); // нахождение целой и дробной части cout << "Целая часть равна " << intpart // вывод результатов << ", дробная часть равна " << fracpart << endl; } while(number != 0.0 ); //выход из цикла, если введен ноль
return 0;
} //--------------------------------------------------------
// функция intfrac()
// вычисляет целую и дробную часть вещественного числа
void intfrac(float n, float& intp, float& fracp) {
long temp = static_cast<long>(n); // преобразование к типу long,
intp = static_cast<float>(temp); // и обратно во float
fracp = n - intp; // вычитаем целую часть
}
Функция main() запрашивает у пользователя значение типа float. Затем про- грамма выделяет целую и дробную часть введенного числа. Например, если пользователь введет число 12.456, то программой будет выдано сообщение о том, что целая часть введенного значения равна 12, а дробная часть равна 0.456. Для выделения целой части числа используется функция intfrac(). Вот пример работы программы:
Введите вещественное число: 99.44
Целая часть равна 99, дробная часть равна 0.44
Некоторые компиляторы могут сгенерировать ложные знаки после десятич- ной точки у дробной части числа, например 0.440002. Это является ошибкой рабо- ты компилятора, а не программы, поэтому можете смело проигнорировать их.

как если бы они были в intfrac()
Рис. 5.7. Передача по ссылке в программе REF
Обратимся к рис. 5.7. Функция intfrac() выделяет из числа целую часть пу- тем преобразования значения, переданного параметру n, в переменную типа long с использованием явного приведения типов:
long temp = static_cast<long>(n);
В результате выполнения такого оператора в переменной temp окажется це- лая часть введенного числа, поскольку при преобразовании вещественного зна- чения к целому дробная часть будет отсечена. Затем целая часть снова преобра- зовывается в тип float:
intp = static_cast<float>(temp);
Дробная часть числа представляет собой разность между исходным числом и его целой частью (отметим, что существует библиотечная функция fmod(), вы- полняющая сходные действия над переменной типа double).
Функция intfrac() нашла целую и дробную часть числа, но каким образом она теперь сможет возвратить найденные значения в функцию main()? Ведь с помо-
щью оператора return можно возвратить только одно значение! Проблема реша- ется путем использования ссылочного механизма. Заголовок функции intfrac() выглядит следующим образом:
void intfrac(float n, float& intp, float& fracp) //Заголовок в определении функции
Аргументы, передаваемые по ссылке, обозначаются знаком &, который следу- ет за типом аргумента:
float& intp
Знак & означает, что intp является псевдонимом для той переменной, которая будет передана в функцию в качестве аргумента. Другими словами, используя имя intp в функции intfrac(), фактически мы оперируем значением переменной intpart функции main(). Знак & (амперсанд) символизирует ссылку, поэтому запись
float& intp
означает, что intp является ссылкой на переменную типа float. Точно так же fracp является ссылкой на переменную типа float, в нашем случае — на переменную fracpart.
Если какие-либо аргументы передаются в функцию по ссылке, то в прототи- пе функции необходимо с помощью знака & указывать соответствующий пара- метр-ссылку:
void intfrac(float, float&, float&); // амперсанды в прототипе
Аналогичным образом знаком & отмечаются ссылочные параметры в опреде- лении функции. Однако обратите внимание на то, что при вызовах функции ам- персанды отсутствуют:
intfrac(number, intpart, fracpart); // амперсанды отсутствуют в вызове
При вызове функции нет смысла сообщать, будет ли передан аргумент по значению или по ссылке.
В то время как переменные intpart и fracpart передаются в функцию по ссылке, переменная number передается по значению. Имена intp и intpart связаны с одной и той же областью памяти, гак же как и пара имен fracp и fracpart. Параметр n не связан с переменной, передаваемой ему в качестве аргумента, поэтому ее значение копируется в переменную n. Поскольку не требуется изменять значение, храня- щееся в переменной number, передача ее в функцию осуществляется по значению.
Программистов на C, вероятно, удивляет, что знак амперсанда используется одновременно для обозначения ссылки на переменную и операции взятия адре- са переменной. Мы рассмотрим вопрос использования амперсанда в главе 10 «Указатели».
12 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
