Как сделать массив указателей на методы?

Я хочу создать массив указателей на методы, чтобы я мог быстро выбрать метод для вызова на основе целого числа. Но я немного борюсь с синтаксисом.

То, что у меня есть сейчас, это:

class Foo {
     private:
        void method1();
        void method2();
        void method3();

        void(Foo::*display_functions[3])() = {
            Foo::method1,
            Foo::method2,
            Foo::method3
        };
};

Но я получаю следующее сообщение об ошибке:

[bf@localhost method]$ make test
g++     test.cpp   -o test
test.cpp:11:9: error: cannot convert ‘Foo::method1’ from type ‘void (Foo::)()’ to type ‘void (Foo::*)()’
   11 |         };
      |         ^
test.cpp:11:9: error: cannot convert ‘Foo::method2’ from type ‘void (Foo::)()’ to type ‘void (Foo::*)()’
test.cpp:11:9: error: cannot convert ‘Foo::method3’ from type ‘void (Foo::)()’ to type ‘void (Foo::*)()’
make: *** [<builtin>: test] Error 1

Вы можете создать std::vector<std::function<...>>.

Jesper Juhl 27.11.2022 16:50

Как насчет функции-члена, принимающей это целое число в качестве параметра и вызывающей соответствующую функцию в switch/case? Гораздо менее хрупкий.

DevSolar 27.11.2022 16:51

Вы пробовали &Foo::method1, &Foo::method2, &Foo::method3?

Sam Varshavchik 27.11.2022 16:52

Чтобы получить указатель на функцию-член, вы всегда должны использовать оператор указателя на &.

Some programmer dude 27.11.2022 16:52

Часто очень трудно понять объявления C, если вы используете стандартные контейнеры, такие как std::array и std::function вместо указателей функций в стиле C, отлаживать намного проще.

Richard Bamford 27.11.2022 17:27
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
68
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Да, можно, нужно только взять адрес из них:

        void(Foo::*display_functions[3])() = {
            &Foo::method1,
            &Foo::method2,
            &Foo::method3
        };

... однако, вероятно, будет лучше, если у вас есть virtual методы для интерфейса или простой метод, который вызывает их все для шаблона с несколькими методами.

Вы можете использовать typedef для типа указателя на ваши методы, а затем хранить свои методы в std::array, содержащем этот тип:

class Foo {
private:
    void method1() {};
    void method2() {};
    void method3() {};

    typedef void (Foo::* FooMemFn)();

    std::array<FooMemFn,3> display_functions = {
        &Foo::method1,
        &Foo::method2,
        &Foo::method3
    };
};

Вместо typedef вы также можете использовать оператор using:

using FooMemFn = void (Foo::*)();

Обратите внимание, что вы должны использовать operator& с методом класса, чтобы получить указатель на метод.

Дополнительное примечание: подумайте о том, чтобы сделать display_functions статическим, если он не будет меняться между различными экземплярами класса.

Не только static. Этот массив может быть даже constexpr в C++20. В частности, gcc может оптимизировать вызов, если индексом является constexpr: godbolt.org/z/44o47rqqd

bitmask 27.11.2022 17:51

Другие вопросы по теме