Поскольку тип возвращаемого значения указан после списка параметров, проще заметить, что функция func() возвращает указатель и что этот указатель указывает на массив из десяти целых чисел.
decltype
decltype
, чтобы объявить тип возвращаемого значения. Например, следующая функция возвращает указатель на один из двух массивов, в зависимости от значения ее параметра:
int odd[] = {1,3,5,7,9};
int even[] = {0,2,4,6,8};
//
decltype(odd) *arrPtr(int i) {
return (i % 2) ? &odd : &even //
}
Тип возвращаемого значения функции arrPtr()
указан как decltype
, свидетельствуя о том, что функция возвращает указатель на любой тип, который имеет odd
. В данном случае этот объект является массивом, поэтому функция arrPtr()
возвращает указатель на массив из пяти целых чисел.
Единственная сложность здесь в том, что следует помнить, что спецификатор decltype
не преобразовывает автоматически массив в указатель соответствующего ему типа. Тип, возвращенный спецификатором decltype
, является типом массива, для которого нужно добавить *
, чтобы указать, что функция arrPtr()
возвращает указатель.
Упражнение 6.36. Напишите объявление функции, возвращающей ссылку на массив из десяти строк, не используя ни замыкающий тип возвращаемого значения, ни спецификатор decltype
или псевдоним типа.
Упражнение 6.37. Напишите три дополнительных объявления для функций предыдущего упражнения. Нужно использовать псевдоним типа, замыкающий тип возвращаемого значения и спецификатор decltype
. Какую форму вы предпочитаете и почему?
Упражнение 6.38. Перепишите функцию arrPtr()
так, чтобы она возвращала ссылку на массив.
Функции, расположенные в одной области видимости, называются print()
приведен в разделе 6.2.4:
void print(const char *cp);
void print(const int *beg, const int *end);
void print(const int ia[], size_t size);
Эти функции выполняют одинаковое действие, но их параметры относятся к разным типам. При вызове такой функции компилятор принимает решение о применении конкретной версии на основании типа переданного аргумента:
int j[2] = {0, 1};
print("Hello World"); //
print(j, end(j) - begin(j)); //
print(begin(j), end(j)); //
Перегрузка функций избавляет от необходимости придумывать (и помнить) имена, существующие только для того, чтобы помочь компилятору выяснить, которую из функций применять при вызове.
main()
Рассмотрим приложение базы данных с несколькими функциями для поиска записи на основании имени, номера телефона, номер счета и т.д. Перегрузка функций позволит определить коллекцию функций, каждая по имени lookup()
, которые отличаются тем, как они осуществляют поиск. Мы сможем вызвать функцию lookup()
, передав значение любого из следующих типов:
Record lookup(const Account&); //
Record lookup(const Phone&); //
Record lookup(const Name&); //
Account acct;
Phone phone;
Record r1 = lookup(acct); //
Record r2 = lookup(phone); //
Здесь у всех трех функций одинаковое имя, но все же это три разные функции. Чтобы выяснить, которую из них вызвать, компилятор использует тип (типы) аргументов.
Перегруженные функции должны отличаться по количеству или типу (типам) своих параметров. Каждая из функций выше получает один параметр, но типы у этих параметров разные.