Лекция 8.1-программирование-«Подробнее о функциях»
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Лекция 8.1-программирование-«Подробнее о функциях»

СОДЕРЖАНИЕ

Два способа передачи аргументов. 2

Как в C++ реализована передача аргументов. 2

Использование указателя для обеспечения вызова по ссылке. 3

Возврат ссылок. 9

Независимые ссылки.. 12

Ограничения при использовании ссылок. 13

Перегрузка функций.. 13

Вопросы для самоконтроля. 19


В этойлекции продолжается изучение функций, рассматриваются три самые важные темы, связанные с функциями C++:

- ссылки;

- перегрузка функций;

- использование аргументов по умолчанию.

 Эти три средства в значительной степени расширяютвозможности функций. Как будет показано ниже:

Ссылка — это неявный указатель.

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

Аргументы по умолчаниюпозволяют определить значение для параметра, которое будет автоматически применено в случае, если соответствующий аргумент не задан.


Два способа передачи аргументов

В языках программирования, как правило, предусматривается два способа,которые позволяют передавать аргументы в функции. Первый называется вызовом по значению (call-by-value). В этомслучае значение аргумента копируется в формальный параметр функции.Следовательно, изменения, внесенные в параметры подпрограммы, не влияют нааргументы, используемые при ее вызове.

Второй способ передачи аргумента подпрограмме называется вызовом по ссылке (call-by-reference). В этом случае в параметр копируется адрес аргумента (а неего значение). В пределах вызываемой подпрограммы этот адрес используетсядля доступа к реальному аргументу, заданному при ее вызове. Это значит, что изменения, внесенные в параметр, окажут воздействие на аргумент, используемыйпри вызове подпрограммы.

Как в C++ реализована передача аргументов

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

// Задание 8.1_1.cpp: определяет точку входа для консольного приложения.

// Изменение параметра при вызове по функции по значению

// не влияет на аргумент.

#include "stdafx.h"

#include <iostream>

using namespace std;

double reciprocal(double x);

int main()

{

  setlocale(LC_ALL, "Russian");

  double t = 10.0;

  cout << "Обратная величина от числа 10.0 равна "

        << reciprocal(t) << "\n";

  cout << "Значение переменной t по-прежнему равно: " << t << "\n";

  return 0;

}

// Функция возвращает обратную величину отзаданного значения,

double reciprocal(double x)

{

  x = 1 / x;     // Вычисляем обратную величину. (Это действие

                             // никак не отражается на значении переменной t

                             // из функции main() .)

  return x;

}

При выполнении эта программа генерирует такие результаты.

Обратная величина от числа 10.0 равна 0.1

Значение переменной t по-прежнему равно: 10

Как подтверждают результаты выполнения этой программы, при выполнении присваивания

х = 1 / х;

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

Возврат ссылок

Функция может возвращать ссылку. В программировании на C++ предусмотрено несколько применений для ссылочных значений, возвращаемых функциями. Рассмотрим некоторые из них.

Если функция возвращает ссылку, это означает, что она возвращает неявныйуказатель на значение, передаваемое ею в инструкции return. Этот факт открывает поразительные возможности: функцию, оказывается, можно использовать влевой части инструкции присваивания! Например, рассмотрим следующую простую программу.

// Задание 1.8_5.cpp: определяет точку входа для консольного приложения.

// Возврат ссылки.

#include "stdafx.h"

#include <iostream>

using namespace std;

double&f();  // <— Эта функция возвращает ссылку на double-значение.

double val = 100.0;

int main()

{

setlocale(LC_ALL, "Russian");

double x;

cout << f() << "\n";

x = f();

cout << x << "\n";      // Отображаем значение переменной х.

f() = 99.1;             // Изменяем значение глобальнойпеременной val.

cout << f() << "\n";    // Отображаем новое значение val.

return 0;

}

// Эта функция возвращает ссылку на double-значение.

double &f()

{

return val;  // Возвращаем ссылку на глобальную на переменную val.

}

Результаты выполнения этой программы таковы:

100

100

99.1

Рассмотрим эту программу подробнее. Судя по прототипу функции f (), онадолжна возвращать ссылку на double-значение. За объявлением функции f()следует объявление глобальной переменной val, которая инициализируется значением 100. При выполнении следующей инструкции в функции main () выводится исходное значение переменной val.

cout ≪ f() <<"\n";                // Отображаем значение val

После вызова функция f () при выполнении инструкции return возвращает ссылку на переменную val.

return val;                           // Возвращаем ссылку на val

Таким образом, при выполнении приведенной выше строки автоматически возвращается ссылка на глобальную переменную val. Эта ссылка затем используется инструкцией cout для отображения значения val.

При выполнении строки

х = f();                      //Присваиваем значение val переменной х.

ссылка на переменную val, возвращенная функцией f (), используется для присвоения значения val переменной х.

А вот самая интересная строка в программе.

f( ) = 99.1 ;               // Изменяем значение глобальной переменной val.

При выполнении этой инструкции присваивания значение переменной val становится равным числу 99,1. И вот почему: поскольку функция f () возвращает ссылку на переменную val, эта ссылка и является приемником инструкции присваивания. Таким образом, значение 99,1 присваивается переменной val косвенно, через ссылку (на нее), которую возвращает функция f ().

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

// Задание 8.1_6.cpp: определяет точку входа для консольного приложения.

// Пример функции, возвращающей ссылку на элемент, массива

#include "stdafx.h"

#include <iostream>

using namespace std;

double &change_it(int i);     // Функциявозвращаетссылку,

double vals[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };

int main()

{

setlocale(LC_ALL, "Russian");

int i;

cout << "Вот исходные значения: ";

for (i = 0; i<5; i++)

       cout << vals[i] <<" ";

cout << "\n";

change_it(1) - 5298.23; // Изменяем 2-йэлемент.

change_it(3) = -98.8;   // Изменяем 4-йэлемент.

cout << "Вот измененные значения: ";

for (i = 0; i<5; i++)

       cout << vals[i] <<" ";

cout << "\n";

return 0;

}

double &change_it(int i)

{

return vals[i];         // Возвращаем ссылку на i-й элемент.

}

Эта программа изменяет значения второго и четвертого элементов массива vals.

Независимые ссылки

Понятие ссылки включено в C++ главным образом для поддержки способа передачи параметров "по ссылке" и для использования в качестве ссылочного типа значения, возвращаемого функцией. Несмотря на это, можно объявить независимую переменную ссылочного типа, которая и называется независимой ссылкой. Однако справедливости ради необходимо сказать, что эти независимые ссылочные переменные используются довольно редко, поскольку они могут "сбить с пути истинного" вашу программу. Сделав (для очистки совести) эти замечания, мы все же можем уделить независимым ссылкам некоторое внимание.

Независимая ссылка должна указывать на некоторый объект. Следовательно, независимая ссылка должна быть инициализирована при ее объявлении. В общем случае это означает, что ей будет присвоен адрес некоторой ранее объявленной переменной. После этого имя такой ссылочной переменной можно применять везде, где может быть использована переменная, на которую она ссылается. И в самом деле, между ссылкой и переменной, на которую она ссылается, практически нет никакой разницы. Рассмотрим, например, следующую программу

// Использование независимой ссылки.

#include "stdafx.h"

#include <iostream>

using namespace std;

int main()

{

setlocale (LC_ALL,"Russian");

int j, k;

int &i = j;                  // независимая ссылка

j = 10;

cout << j <<" " << i;                  // Выводится: 10 10

k = 121;

i = k;                                         // Копирует в переменную j значение

// переменной к, а не адрес переменной к.

cout <<"\n" << j; // Выводится: 121

return 0;

}

При выполнении эта программа выводит следующие результаты.

10 10

121

Адрес, который содержит ссылочная переменная, фиксирован и его изменить нельзя. Следовательно, при выполнении инструкции

i = k;

в переменную j (адресуемую ссылкой i ) копируется значение переменной к, а не ее адрес.

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

Перегрузка функций

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

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

Рассмотрим простой пример перегрузки функций

// «Трёхкратная перегрузка функции f()

#include "stdafx.h"

#include <iostream>

using namespace std;

// Для каждой версии перегруженной функции необходимо

// включить в программу отдельный прототип.

void f(int i);                          // один целочисленный параметр

void f(int i, int j);                 // два целочисленных параметра

void f(double k);                  // один параметр типа double

int main()

{

setlocale (LC_ALL,"Russian");

f(10);                   // вызов функции f(int)

f(10, 20); // вызов функции f(int, int)

f(12.23); // вызов функции f(double)

return 0;

}

// Первая реализация функции f().

void f(int i)

{

cout << "В функции f(int), i равно " << i <<"\n";

// Вторая реализация функции f().

void f(int i, int j)

{

cout << "В функции f(int, int), i равно " << i;

cout <<", j равно " << j << "\n";

}

// Третья реализация функции f().

void f(double k) .

{

cout << " В функции f(double), k равно " << k << "\ n";

}

Вопросы для самоконтроля

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

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

3. Какой механизм передачи параметров используется в C++ по умолчанию?

4. Как объявить параметр-ссылку?

5. Нужно ли предварять аргумент символом "&" при вызове функции, которая принимает ссылочный параметр?

6.  Нужно ли предварять параметр символам и " *" или " &" при выполнении операций над ними в функции, которая принимает ссылочный параметр?

7. Может ли функция возвращать ссылку?

8. Что представляет собой независимая ссылка?

9. Можно ли создать ссылку на ссылку?

10. Какие условия должны соблюдаться при перегрузке функции?

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

12. Учитывается ли тип значения, возвращаемого функцией, в решении о выборе нужной версии перегруженной функции?

Лекция 8.1-программирование-«Подробнее о функциях»

СОДЕРЖАНИЕ

Два способа передачи аргументов. 2

Как в C++ реализована передача аргументов. 2

Использование указателя для обеспечения вызова по ссылке. 3

Возврат ссылок. 9

Независимые ссылки.. 12

Ограничения при использовании ссылок. 13

Перегрузка функций.. 13

Вопросы для самоконтроля. 19


В этойлекции продолжается изучение функций, рассматриваются три самые важные темы, связанные с функциями C++:

- ссылки;

- перегрузка функций;

- использование аргументов по умолчанию.

 Эти три средства в значительной степени расширяютвозможности функций. Как будет показано ниже:

Ссылка — это неявный указатель.

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

Аргументы по умолчаниюпозволяют определить значение для параметра, которое будет автоматически применено в случае, если соответствующий аргумент не задан.


Дата: 2019-05-29, просмотров: 158.