У меня есть большой код, в середине которого есть ошибка. Вот упрощенная версия частей кода, в которых есть ошибка.

И вот какую ошибку я получаю:

// Followings are declared in the header

struct Task {
public:
    _COORD p1;
    int p2;
    object p3;
    speed p4;
    bool(Game::*function)(_COORD, int, object, speed);
};


std::vector tasks;

// Followings are defined in the source

void Game::timer() {
    (some code here)
tasks[i].function(tasks[i].p1, tasks[i].p2, tasks[i].p3, tasks[i].p4);     /*error here*/

выражение, предшествующее круглым скобкам явного вызова, должно иметь (указатель на) тип функции.

}

void Game::explode(bool(Game::*function)(_COORD, int, object, speed), _COORD p1, int p2, object p3, speed p4) {
    ExplodeTask task;
    task.function = function;
    task.p1 = p1;
    task.p2 = p2;
    task.p3 = p3;
    task.p4 = p4;
    tasks.push_back(task);
}

Кто-нибудь знает, как это исправить?

Ответы (2)

Правильный синтаксис для вызова указателя функции метода - (objectPtr->*methodPtr)() или (object.*methodPtr)():

.
void Game::timer() {
    int i = 0;
    ...
    (this->*tasks[i].function)(tasks[i].p1, tasks[i].p2, tasks[i].p3, tasks[i].p4);
}

Советую использовать std::function вместо указателя функции. Синтаксис Std::function более дружественный, ему можно присвоить любой тип функции, от сырых функций до выражений lamdba. Также мне кажется немного странным, что вы передаете p1,p2,p3,p4 как параметры функции, даже если они константные. Это будет сложнее использовать таким образом. По крайней мере, вы могли бы переопределить оператор (). И вызывать передачу параметров с помощью оператора () один раз, тогда пользователю не нужно будет передавать параметр второй раз в функции "таймер".

Если вы должны использовать указатель функции, я думаю, что это лучше:

struct Task {
public:
    int p1;
    int p2;
    int p3;
    int p4;
    bool operator()()
    {
        return (functionPtr)(p1,p2,p3,p4);
    }
    bool(*functionPtr)(int, int, int, int );
};

Task t { 1, 2 ,3 ,4, &Game::foo(int, int, int, int) };

Than client can make a easy call without passing parameters like. 
t();

чтобы клиент класса Task мог легко вызывать task() напрямую.

ИМХО код будет лучше, как :

#include 
#include 

std::vector> functionList;

void taskPusher( std::function foo , int p1, int p2, int p3, int p4)
{

    std::function explodeTask = [=]()
    {
        return foo(p1,p2,p3,p4);
    } ;

    functionList.push_back(explodeTask);
}

void explode()
{
    for ( auto& explodeFoo : functionList)
    {
        explodeFoo();
    }
}

2022 WebDevInsider