int calc(const char*, const char*);
(c) int calc(char*, char*);
int calc(char* const, char* const);
6.7. Указатели на функции
//
bool lengthCompare(const string &, const string &);
Эта функция имеет тип bool(const string&, const string&)
. Чтобы объявить указатель, способный указывать на эту функцию, достаточно расположить указатель вместо имени функции:
//
//
bool (*pf)(const string &, const string &); //
Просматривая объявление с начала, можно заметить, что имени pf
предшествует знак *
, следовательно, pf
— указатель. Справа расположен список параметров, означая, что pf указывает на функцию. Глядя влево, можно заметить, что возвращаемым типом функции является bool
. Таким образом, указатель pf
указывает на функцию, которая имеет два параметра типа const string&
и возвращает значение типа bool
.
*pf
необходимы. Без них получится объявление функции pf()
, возвращающей указатель на тип bool
:
//
bool *pf(const string &, const string &);
При использовании имени функции как значения функция автоматически преобразуется в указатель. Например, адрес функции lengthCompare()
можно присвоить указателю pf следующим образом:
pf = lengthCompare; //
pf = &lengthCompare //
//
Кроме того, указатель на функцию можно использовать для вызова функции, на которую он указывает. Это можно сделать непосредственно, обращение к значению указателя там не обязательно:
bool b1 = pf("hello", "goodbye"); //
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; //
pf = sumLength; //
pf = cstringCompare; //
pf = lengthCompare; //
Как обычно, при использовании перегруженной функции применяемую версию должен прояснить контекст, в котором она используется. Вот объявление указателя на перегруженную функцию:
void ff(int*);
void ff(unsigned int);
void (*pf1)(unsigned int) = ff; //
Компилятор использует тип указателя для выявления используемой версии перегруженной функции. Тип указателя должен точно соответствовать одной из версий перегруженной функции:
void (*pf2)(int) = ff; //
//
double (*pf3) (int*) = ff; //
//