class name {
public:
name(int);
double(*act)(double);
double f1(double);
double f2(double);
double f3(double);
};
name::name(int i) {
this->act = new (double[i](double));
}
error: creating array of functions
Вот так ругается компилятор. Как можно реализовать такой динамический массив?
Ответ
Если говорить про обычные функции:
int foo1(float)
{
return 1;
}
int foo2(float)
{
return 2;
}
int foo3(float)
{
return 3;
}
int main()
{
// в типе должна быть описана сигнатура необходимой функции
using fun_type = int(*)(float); // int - возвращаемый тип
// float - аргумент, (*) - означает что мы хотим создать указатель на функцию
// создали массив указателей на функции
// поместили адреса фукций foo1, foo2, foo3
fun_type funs[] = { &foo1, &foo2, &foo3 };
// вызываем функцию (в данном случае foo1)
int result = funs[0](10.0f);
return 0;
}
Однако в вашем случае необходимы не просто указатели на функцию, а указатели на методы класса. Это другие сущности и, настолько они особенны, что даже не поддаются void*. Но такая проблема также решается:
class widget
{
public:
// имеется несколько методов с одинаковой сигнатурой
void foo1(int);
void foo2(int);
void foo3(int);
// внимание на модификатор const
// объяснения ниже
void foo4_c(int) const;
};
int main()
{
// объявление массива указателей на метод класса widget
// как и в случае с обычным указателем, этот указатель
// просто локальная переменная
// эти указатели не относятся к какому-нибудь конкретному объекту
// они относятся к классу widget в целом
void(widget::*fun_ptr[3])(int);
// устанавливаем несколько конкретных значений
// можно было при объявлении инициализировать списком {}
fun_ptr[0] = &widget::foo1;
fun_ptr[1] = &widget::foo2;
fun_ptr[2] = &widget::foo3;
// по поводу const в объявлении метода:
// const является часть сигнатуры метода!
// поэтому следующий код не скомпилируется
// по причине разных типов указателей
// fun_ptr[2] = &widget::foo4_c; // error!
// для const-методов необходимо указать спецификатор const
void(widget::*const_fun_ptr)(int) const;
const_fun_ptr = &widget::foo4_c; // ok!
// создается конкретный объект класса
widget obj;
// и указатель на динамически распределенный объект
widget *ptr_to_obj = new widget();
// собственно использование указателей
// obj.* - обращение к члену указателю
// т.к. fun_ptr массив мы указываем еще индекс
// по которому находится нужный метод
// необходимо взять в скобки
(obj.*fun_ptr[0])(10);
// для указателей на объекты используется
// чуть-чуть другой синтаксис
(ptr_to_obj->*fun_ptr[0])(10);
delete ptr_to_obj;
return 0;
}
Создать динамический массив указателей на обычную функцию не слишком сложно.
using fptr = void(*)(int);
fptr* fptrs = new fptr[10];
delete[] fptrs;
Чуть сложнее дело обстоит с указателями на методы. У меня получилось достичь необходимого результата следующим образом:
#include
class widget
{
public:
void foo1(int)
{
std::cout << "foo1
";
}
void foo2(int)
{
std::cout << "foo2
";
}
void foo3(int)
{
std::cout << "foo3
";
}
};
int main()
{
void(widget::*fptr)(int);
using fptr_type = decltype(fptr);
fptr_type* fptrs = new fptr_type[3];
fptrs[0] = &widget::foo1;
fptrs[1] = &widget::foo2;
fptrs[2] = &widget::foo3;
widget a;
(a.*fptrs[0])(10);
(a.*fptrs[1])(10);
(a.*fptrs[2])(10);
delete[] fptrs;
std::cin.get();
return 0;
}
Комментариев нет:
Отправить комментарий