Как выделить память для массива функций

205
06 сентября 2018, 18:00
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

Вот так ругается компилятор. Как можно реализовать такой динамический массив?

Answer 1

Если говорить про обычные функции:

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 <iostream>
class widget
{
public:
    void foo1(int)
    {
        std::cout << "foo1\n";
    }
    void foo2(int)
    {
        std::cout << "foo2\n";
    }
    void foo3(int)
    {
        std::cout << "foo3\n";
    }
};
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;
}
Answer 2

Вы хотите что-то вроде этого?

class Name {
public:
    Name(int);
    using func = double(*)(double);
    func* act;
};
Name::Name(int i)
{
    act = new func[i];
}

На всякий случай, исходя из набора у вас функций-членов f# - для функций-членов массив надо объявлять иначе.

READ ALSO
Хранение множества продуктов

Хранение множества продуктов

У меня есть база данных и 3 таблицы: ProductEntity, OrderEntity и ProductInOrder

173
Как настроить в .properties log4j путь к логам внутри проекта?

Как настроить в .properties log4j путь к логам внутри проекта?

Друзья, здравствуйте, Подскажите как настроить вproperties log4j путь к логам внутри проекта? То есть что бы после пула с гита путь был всегда октуален

210
Воспроизведение midi в java

Воспроизведение midi в java

Я использую библиотеку JMusic для редактора MIDI (и AU) файлов:http://explodingartcom/jmusic/index

229