【问题标题】:how to properly call a function when it is a pointer to a class function but is outside that class当函数是指向类函数的指针但在该类之外时如何正确调用函数
【发布时间】:2014-01-26 15:15:39
【问题描述】:

对不起,如果这个标题措辞不好......但这就是我想要做的......

我有一个结构“screen”,它有一个指向这些函数的指针,这些函数是“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);

     ...

}

我像这样在创建我的测试实例“test”时分配drawfunc指针......这对我来说看起来很奇怪,我不完全理解它,但它编译......

Test::Test()
{

     ...

     tscreen->drawfunc=&Test::draw;

     ...

}

但我无法弄清楚如何在我的 main 中调用 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从哪个类“Test”实例工作......即使所有变量和指向函数本身的指针都来自实例“test”。 ..

...对于不可避免的“你为什么要这样做?”回复......或者如果没有办法调用该函数或其他东西......我真的只是希望能够将不同的函数分配给“drawfunc”并且我希望这些函数能够使用所有变量在实例“test”中,我可以得到它,所以 drawfunc 指向任何旧函数( bool (drawfunc)(b2World, objectdata*, actorlist*, camera*); ),但它需要能够访问测试实例“test”中的其他变量。所以......真的,不管你怎么做,那也很棒。谢谢。

【问题讨论】:

  • 为什么不放一个更简单但完整的示例,将您的问题反映到您的问题中。因为对于你所拥有的,很难给你一个正确的答案。

标签: c++ class pointers struct function-pointers


【解决方案1】:

你这样做:

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

通常,间接指向成员的指针涉及使用->*.* 运算符。如果你有一个指向对象a 的指针和一个指向成员b 的指针,那么你会说a ->* b。在您的情况下,指向对象的指针是test,指向成员的指针是test->tscreen->drawfunc。额外的括号是必要的,因为->* 是一个二元运算符,它的优先级低于后缀函数调用运算符(),但您希望在调用它之前间接指向成员。

【讨论】:

  • 哇,谢谢!我永远也想不通。你先生是某种天才!
【解决方案2】:

最简单的方法是不直接使用函数指针,而是用像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(); 
}

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?
    }
}

【讨论】:

  • @MikeDeSimone 可以删除 lambda 示例,我确信可以轻松模拟 std::bind()。或者只使用boost::bind()。重点是:有办法让这种代码变得清晰,抛弃所有的指针诡计。
  • 对不起,这一切让我很困惑......我什至不知道如何使用 cout 或那些“
猜你喜欢
  • 2021-12-21
  • 2014-10-03
  • 1970-01-01
  • 2017-08-30
  • 1970-01-01
  • 2012-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多