int calc(const char*, const char*);

(c) int calc(char*, char*);

    int calc(char* const, char* const);

<p>6.7. Указатели на функции</p>

Указатель на функцию (function pointer) содержит адрес функции, а не объекта. Подобно любому другому указателю, указатель на функцию имеет вполне определенный тип. Тип функции определен типом ее возвращаемого значения и списком параметров. Имя функции не является частью ее типа.

// сравнивает длины двух строк

bool lengthCompare(const string &, const string &);

Эта функция имеет тип bool(const string&, const string&). Чтобы объявить указатель, способный указывать на эту функцию, достаточно расположить указатель вместо имени функции:

// pf указывает на функцию, получающую две константные ссылки

// на строки и возвращающую значение типа bool

bool (*pf)(const string &, const string &); // не инициализирован

Просматривая объявление с начала, можно заметить, что имени pf предшествует знак *, следовательно, pf — указатель. Справа расположен список параметров, означая, что pf указывает на функцию. Глядя влево, можно заметить, что возвращаемым типом функции является bool. Таким образом, указатель pf указывает на функцию, которая имеет два параметра типа const string& и возвращает значение типа bool.

Круглые скобки вокруг части *pf необходимы. Без них получится объявление функции pf(), возвращающей указатель на тип bool:

// объявление функции pf(), возвращающей указатель на тип bool

bool *pf(const string &, const string &);

Использование указателей на функцию

При использовании имени функции как значения функция автоматически преобразуется в указатель. Например, адрес функции lengthCompare() можно присвоить указателю pf следующим образом:

pf = lengthCompare;  // pf теперь указывает на функцию lengthCompare

pf = &lengthCompare // эквивалентное присвоение: оператор обращения к

                     // адресу необязателен

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

bool b1 = pf("hello", "goodbye");            // вызов lengthCompare

bool b2 = (*pf)("hello", "goodbye");         // эквивалентный вызов

bool b3 = lengthCompare("hello", "goodbye"); // эквивалентный вызов

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

string::size_type sumLength(const string&, const string&);

bool cstringCompare(const char*, const char*);

pf = 0;              // ok: pf не указывает на функцию

pf = sumLength;      // ошибка: разные типы возвращаемого значения

pf = cstringCompare; // ошибка: разные типы параметров

pf = lengthCompare;  // ok: типы функции и указателя совпадают точно

Указатели на перегруженные функции

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

void ff(int*);

void ff(unsigned int);

void (*pf1)(unsigned int) = ff; // pf1 указывает на ff(unsigned)

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

void (*pf2)(int) = ff;     // ошибка: нет версии с точно таким списком

                           // параметров

double (*pf3) (int*) = ff; // ошибка: тип возвращаемого значения

                           // функций ff и pf3 не совпадают

Перейти на страницу:

Похожие книги