Указатель — это объект, который умеет хранить адреса.
На любой объект можно создать указатель.
В указатель можно присвоить адрес
Имя функции умеет неявно приводиться к указательной переменной. Поскольку имя функции может стать указателем, то в подходящий для функции указатель можно присвоить адрес функции.
Мне определённо кажется, что вместо кучи разных и непонятных слов к этой статье подойдёт небольшая подборка примеров кода.
Общий принцип построения указателя на функцию: Тип_Функции(*Имя_Функции)(СПИСОК_ФОРМАЛЬНЫХ_ПАРАМЕТРОВ_ФУНКЦИИ)
Обязательно к имени функции приклеивать слева указательное обозначение и заворачивать это дело скобками.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
voidfoo1(){std::cout<<"foo1\n";}
voidfoo2(){std::cout<<"foo2\n";}
voidfoo3(constint){std::cout<<"foo3\n";}
intfoo4(constint){std::cout<<"foo4\n";return10;}
intmain()
{
void(*ptr_foo1)();//указатель на функцию foo1
ptr_foo1=&foo1;
void(*ptr_foo2)();//указатель на функцию foo2
ptr_foo2=&foo2;
void(*ptr_foo3)(int);//указатель на функцию foo3
ptr_foo3=&foo3;
int(*ptr_foo4)(int);//указатель на функцию foo4
ptr_foo4=&foo4;
/*ВЫЗОВ ПРОИСХОДИТ ОБЫЧНЫМ ОБРАЗОМ*/
ptr_foo1();//вызвали указателем
ptr_foo2();
//ptr_foo3(); //так нельзя, потому что указатель указывает
//на функцию с параметром
ptr_foo3(7);//поэтому так правильно
std::cout<<ptr_foo4(77);//вывод 10, без аргумента будет ошибка компиляции
}
Пример достаточно мал, поэтому его должно быть можно быстро понять. Важно только не забывать, что имя функции обозначается как указательная сущность и оборачивается скобками и что должно быть соответствие в параметрах.
Отдельного упоминания заслуживает указательная переменная, указывающая на экземпляр шаблонной функции.
Указатель на шаблон функции создать нельзя, но указатель на экземпляр функции создать можно.
Функции, которые объявлены как шаблонные, вроде и есть, а указатель на них создать нельзя. Нельзя создать указатель на шаблон функции по той простой причине, что шаблон функции являет собой целое семейство функций. Другими словами — шаблон функций обозначает множество разных функций сразу. Так как указатель в один момент времени может указывать только на один тип, да и вообще в С++ динамически типы изменять нельзя, то указать на шаблон функции нельзя. Но на представителя семейства указатель создавать можно.
Пример создания указателя на экземпляр шаблонной функции:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
usingstd::cout;
template<classT1,classT2,classT3>
T3f(T1x,T2y)
{
T3 temp;
cout<<x<<' '<<y<<'\n';
returntemp;
}
intmain()
{
bool(*ft)(double,int);//Указатель на функцию c параметрами double,int
ft=f<double,int,bool>;//НЕ ЗАБЫВАЕМ, УКАЗАТЬ УКАЗАТЕЛЮ НА ЧТО-НИБУДЬ
ft(50,70);//вызов функции
/*Можно создавать указатели на экземпляры семейства функций*/
int(*ptr1)(double,constchar*);
constchar*(*ptr2)(constchar*,constchar*);
float(*ptr3)(int,int);
/*Ссылаться на совместимые для указателя экземпляры*/
ptr1=f<double,constchar*,int>;
ptr2=f<constchar*,constchar*,constchar*>;
ptr3=f<int,int,float>;
/*И использовать при необходимости*/
ptr1(100,"HELLO");
ptr2("ptr2","text");
ptr3(100,200);
}
В показанном примере третий шаблонный параметр T3 в ходе работы программы принимает типы, не умеющие преобразовываться друг к другу. Поэтому его трудно будет задействовать. Конечно это решаемо, но эта статья об указателях на экземпляры шаблонных функций, поэтому не буду затрагивать другую тему. Позже вы к ней ещё придёте.
Задавая аргументы или явно (где необходимо задать всё явно), или неявно (если все параметры шаблона могут сами подставить в себя типы из приходящих в шаблон типов значений) в момент использования указательной переменной как функции — мы получаем возможность возложить обязанности работы функции на плечи указательной переменной. Единственное, нужно смотреть совместимость параметров, приписанных к указательной переменной, и параметров, живущих в экземпляре функции, с которой указатель связывается.
Тут важно понять сам принцип, остальное всё проще, чем может показаться на первый взгляд. И важно запомнить, что указательную переменную можно связать только с одним экземпляров шаблонной функции, а не со всем семейством, зарождаемым шаблонной функцией.
Добавить комментарий