- •Функции, часть 2:
- •-Ссылка — это неявный указатель.
- •Два способа передачи аргументов
- •2. При вызове по ссылке функции передается адрес аргумента.
- •void swap(int *х, int *у)
- •Результаты выполнения этой программы
- •Ссылочные параметры
- •При использовании ссылочного параметра функции автоматически передается адрес (а не значение) аргумента.
- •При выполнении этой программы получаем такой результат.
- •Инструкция
- •void swap(int &х, int &у)
- •Присваивая некоторое значение ссылке, вы в действительности присваиваете это значение переменной, на которую
- •Объявление ссылочных параметров
- •Некоторые программисты определяют в таком стиле и указатели, связывая символ "*" с типом,
- •Подобное связывание символа "&" или "*" с типом (а не с переменной) не
- •Возврат ссылок
- •Вот как выглядят результаты выполнения этой программы.
- •Результаты ее выполнения таковы.
- •//Здесь ошибка: нельзя возвращать
- •Создание ограниченного массива
- •// Функция занесения значения в массив. int &put(int i)
- •Результат, полученный при выполнении этой программы, выглядит так.
- •Независимые ссылки
- •Ограничения при использовании ссылок
- •Перегрузка функций
- •void f(int i)
- •При выполнении эта программа генерирует следующие результаты.
- •Чтобы лучше понять выигрыш от перегрузки функций, рассмотрим три функции из стандартной библиотеки:
- •// Создание функций myabs() — перегруженной версии функции abs().
- •int myabs(int i)
- •Результаты выполнения этой программы таковы.
- •Принципиальная значимость перегрузки состоит в том, что она позволяет обращаться к связанным функциям
- •Благодаря полиморфизму программисту нужно помнить не три различных имени, а только одно.
- •Анахронизм в виде ключевого
- •Аргументы, передаваемые функции по умолчанию
- •Чтобы предусмотреть максимально возможное количество ситуаций и обеспечить их корректную обработку, функции часто
- •Аргумент, передаваемый функции по умолчанию, представляет собой
- •При создании функций, имеющих значения аргументов, передаваемых по умолчанию, необходимо помнить, что значения
- •Важно понимать, что все параметры, которые принимают значения по умолчанию, должны быть расположены
- •void mystrcat(char *s1, char *s2, int len);
- •// Применение пользовательской версии функции strcat()
- •// Пользовательская версия функции strcat().
- •Перегрузка функций и неоднозначность
- •Неоднозначность в программе вызвана не перегрузкой функции myfunc(), объявленной дважды для приема double-
- •Неоднозначность может быть также вызвана использованием в перегруженных функциях аргументов, передаваемых по умолчанию.
// Применение пользовательской версии функции strcat()
#include <iostream>
#include <cstring> using namespace std;
void mystrcat(char *s1, char *s2, int len = -1); int main()
{
char str1[80] = "Это тест.";
char str2[80] = "0123456789";
mystrcat(str1, str2, 5); // Присоединяем 5 символов.
cout << str1 << '\n';
strcpy(str1, "Это тест."); // Восстанавливаем str1.
mystrcat(str1, str2); // Присоединяем всю строку.
cout << str1 << '\n';
return 0;
}
// Пользовательская версия функции strcat().
void mystrcat(char *s1, char *s2, int len)
{
// Находим конец строки s1.
while(*s1) s1++;
if(len == -1) len = strlen(s2);
while(*s2 && len)
{
*s1 = *s2; // Копируем символы.
s1++; s2++; len--;
}
*s1 = '\0'; // Завершаем строку s1 нулевым символом.
}
Перегрузка функций и неоднозначность
Неоднозначность возникает тогда, когда компилятор не может определить различие между двумя перегруженными функциями.
Основной причиной неоднозначности в C++ является автоматическое преобразование типов. В C++ делается попытка автоматически преобразовать тип аргументов, используемых для вызова функции, в тип параметров, определенных функцией. Рассмотрим пример.
int myfunc(double d); cout << myfunc('c');
// Неоднозначность вследствие перегрузки функций. #include <iostream>
using namespace std; float myfunc(float i); double myfunc(double i); int main()
{
// Неоднозначности нет, вызывается функция myfunc(double).
cout << myfunc (10.1) << " ";
// Неоднозначность.
cout << myfunc(10);
return 0;
}
float myfunc(float i)
{
return i;
}
double myfunc(double i)
{
return -i;
}
Неоднозначность в программе вызвана не перегрузкой функции myfunc(), объявленной дважды для приема double- и float-аргумента, а использованием при конкретном вызове функции myfunc() аргумента неопределенного для преобразования типа. Другими словами, ошибка состоит не в перегрузке функции myfunc(), а в конкретном ее вызове.
// Еще одна ошибка, вызванная неоднозначностью. #include <iostream>
using namespace std;
char myfunc(unsigned char ch); char myfunc(char ch);
int main()
{
cout << myfunc('c'); // Здесь вызывается myfunc(char).
cout << myfunc(88) << " "; // Вносится неоднозначность.
return 0;
}
char myfunc(unsigned char ch)
{
return ch-1;
}
char myfunc(char ch)
{
return ch+1;
}
Неоднозначность может быть также вызвана использованием в перегруженных функциях аргументов, передаваемых по умолчанию.
// Еще один пример неоднозначности. #include <iostream>
using namespace std; int myfunc(int i);
int myfunc(int i, int j=1); int main()
{
cout << myfunc(4, 5) << " "; // неоднозначности нет
cout << myfunc(10); // неоднозначность
return 0;
}
int myfunc(int i)
{
return i;
}
int myfunc(int i, int j)
{
return i*j;
}