2014-01-26 3 views
1

Извините, если это название сформулировано плохо ... но вот что я пытаюсь сделать ...как правильно вызвать функцию, когда она является указателем на функцию класса, но за пределами этого класса

I «ве получил STRUCT„экран“, который имеет указатель на эти функции, которые являются членами класса„Test“...

typedef struct screen{ 

    ... 

    bool (Test::*drawfunc)(b2World*, objectdata*, actorlist*, camera*);  

    ... 

} 

class Test{ 

    ... 

    screen* tscreen; 

    bool Test::draw(b2World* world, objectdata* objects, actorlist* al, camera* cam); 

    ... 

} 

поручает указатель drawfunc в создании моего тестового экземпляра„тест“, как это ... и это выглядит странно для меня, я не совсем понимаю это, но оно компилируется ...

Test::Test() 
{ 

    ... 

    tscreen->drawfunc=&Test::draw; 

    ... 

} 

, но я не могу понять, как вызвать функцию drawfunc в моей основной ... Я пробую это так, и это дает ошибку «ошибка C2064: термин не оценивает функцию с 4 аргументами»

int main (int acrgc, char** argv){ 

    ... 

    Test* test = new Test(); 

    test->tscreen->drawfunc(test->m_world, test->objects, test->tscreen->al, test->tscreen->cam); 

    ... 

} 

Я знаю, что вызов неправильный, я никогда не указываю, какой экземпляр класса «Тест» для drawfunc работать из ... хотя все переменные и указатель на эту функцию принадлежат экземпляру " тест "...

... и за неизбежное" Почему вы все равно пытаетесь это сделать? " ответ ... или в случае, если нет способа вызвать эту функцию или что-то еще ... Я просто хочу, чтобы иметь возможность назначать разные функции «drawfunc», и я хочу, чтобы эти функции могли использовать все переменные внутри экземпляра «test», я могу получить его так, чтобы drawfunc указывал на любую старую функцию (bool (drawfunc) (b2World, objectdata *, actorlist *, camera *);), но он должен иметь возможность доступа к другому переменные внутри тестового экземпляра «test». Итак ... действительно, как бы вы ни делали, это было бы здорово. Благодарю.

+0

Почему бы не поместить немного более простой, но полный образец, который отражает вашу проблему в вашем вопросе. Как это довольно сложно дать вам правильный ответ за то, что у вас есть. –

ответ

2

Вы сделать это следующим образом:

(test ->* test->tscreen->drawfunc)(test->m_world, test->objects, test->tscreen->al, test->tscreen->cam); 

В общем, indirecting член указатель на вовлекает использование ->* или .* операторов. Если у вас есть указатель на объект a и указатель-на-член b, тогда вы скажете a ->* b. В вашем случае ваш указатель на объект - test, а ваш указатель на член - test->tscreen->drawfunc. Дополнительные скобки необходимы, потому что ->* является двоичным оператором, который имеет более низкий приоритет, чем оператор вызова функции постфикса (), но вы хотите косвенно косвенно указать указатель на него, прежде чем вызывать его.

+0

WOW СПАСИБО! Я бы никогда не подумал об этом. Вы, сэр, какой-то гений! – user3237682

1

Самый простой способ - не использовать указатели функций напрямую и обертывать их такими функторами, как std::function. В случае функций-членов, использовать std::bind() связать объект в функтор:

struct foo 
{ 
    void f() 
    { 
     std::cout << "f()!" << std::endl; 
    } 
}; 

int main() 
{ 
    foo my_foo; 

    auto f_wrapper = std::bind(&foo::f , my_foo); 

    f(); 
} 

п()!

Это позволяет легко передавать различные функции функции или что-то еще. Например:

class a_class_which_does_complex_drawings 
{ 
    void draw(); 
}; 

void a_global_function_which_draws_things(); 


template<typename DRAW_FUNCT> 
void the_function_which_really_draws(DRAW_FUNCT drawing_method) 
{ 
    drawing_method(); //Tah dah! 
} 

int main() 
{ 
    typedef std::function<void()> drawing_callback_t; 
    std::vector<drawing_callback_t> callbacks; 

    a_class_which_does_complex_drawings mi_complex_drawer; 


    callbacks.push_back(a_global_function_which_draws_things); //Works 
    callbacks.push_back(std::bind(&a_class_which_does_complex_drawings::draw , 
            my_complex_drawer)); //Why not? Of course works 

    callback.push_back([](){ /* draw code */ }); //Ohhh, a lambda! Also works 

    //Simulation/Drawing/Game loop 
    while(true) 
    { 
     for(auto& callback : callback) 
      the_function_which_really_draws(callback); //Magic, isn't? 
    } 
} 
+0

Это, конечно же, требует поддержки C++ 11. –

+0

@MikeDeSimone пример lambda может быть удален, и я уверен, что 'std :: bind()' можно легко моделировать. Или просто используйте 'boost :: bind()'.Дело в том, что: ** Есть способы сделать этот код понятным, отбросив всю эту хитрость указателя. ** – Manu343726

+0

Извините, это все очень смущает меня ... я даже не знаю, как использовать cout или тех "<<" операторов полностью. Но мне нужно назначить drawfunc при создании теста (мой третий блок кода), в этот момент нет теста (экземпляр Test) для привязки функции. Я думаю, мой вопрос для вашего ответа заключается в том, как вы ссылаетесь на создаваемый объект как на его создание (чтобы его можно было привязать)? Кроме того, это похоже на странную работу, нет ли способа вызвать эту функцию, которую я пытаюсь вызвать? – user3237682

Смежные вопросы