Страницы

Поиск по вопросам

среда, 1 января 2020 г.

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

#cpp #ооп #функции #динамические_массивы


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



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


Ответы

Ответ 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 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; }

Ответ 2



Вы хотите что-то вроде этого? class Name { public: Name(int); using func = double(*)(double); func* act; }; Name::Name(int i) { act = new func[i]; } На всякий случай, исходя из набора у вас функций-членов f# - для функций-членов массив надо объявлять иначе.

Комментариев нет:

Отправить комментарий