如何传递成员函数指针?

发布于 2024-07-05 06:59:53 字数 870 浏览 5 评论 0原文

我试图将类中的成员函数传递给采用成员函数类指针的函数。 我遇到的问题是我不确定如何使用 this 指针在类中正确执行此操作。 有人有建议吗?

下面是传递成员函数的类的副本:

class testMenu : public MenuScreen{
public:

bool draw;

MenuButton<testMenu> x;

testMenu():MenuScreen("testMenu"){
    x.SetButton(100,100,TEXT("buttonNormal.png"),TEXT("buttonHover.png"),TEXT("buttonPressed.png"),100,40,&this->test2);

    draw = false;
}

void test2(){
    draw = true;
}
};

函数 x.SetButton(...) 包含在另一个类中,其中“object”是模板。

void SetButton(int xPos, int yPos, LPCWSTR normalFilePath, LPCWSTR hoverFilePath, LPCWSTR pressedFilePath, int Width, int Height, void (object::*ButtonFunc)()) {

    BUTTON::SetButton(xPos, yPos, normalFilePath, hoverFilePath, pressedFilePath, Width, Height);

    this->ButtonFunc = &ButtonFunc;
}

如果有人对我如何正确发送此功能有任何建议,以便我以后可以使用它。

I am trying to pass a member function within a class to a function that takes a member function class pointer. The problem I am having is that I am not sure how to properly do this within the class using the this pointer. Does anyone have suggestions?

Here is a copy of the class that is passing the member function:

class testMenu : public MenuScreen{
public:

bool draw;

MenuButton<testMenu> x;

testMenu():MenuScreen("testMenu"){
    x.SetButton(100,100,TEXT("buttonNormal.png"),TEXT("buttonHover.png"),TEXT("buttonPressed.png"),100,40,&this->test2);

    draw = false;
}

void test2(){
    draw = true;
}
};

The function x.SetButton(...) is contained in another class, where "object" is a template.

void SetButton(int xPos, int yPos, LPCWSTR normalFilePath, LPCWSTR hoverFilePath, LPCWSTR pressedFilePath, int Width, int Height, void (object::*ButtonFunc)()) {

    BUTTON::SetButton(xPos, yPos, normalFilePath, hoverFilePath, pressedFilePath, Width, Height);

    this->ButtonFunc = &ButtonFunc;
}

If anyone has any advice on how I can properly send this function so that I can use it later.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

罗罗贝儿 2024-07-12 06:59:53

其他人已经告诉你如何正确地做到这一点。 但令我惊讶的是,没有人告诉您这段代码实际上是危险的:

this->ButtonFunc = &ButtonFunc;

由于 ButtonFunc 是一个参数,因此当函数返回时它将超出范围。 你正在获取它的地址。 您将获得一个 void (object::**ButtonFunc)() 类型的值(指向成员函数的指针)并将其分配给 this->;按钮功能 当您尝试使用 this->ButtonFunc 时,您将尝试访问(现在不再存在)本地参数的存储,并且您的程序可能会崩溃。

我同意Commodore的解决方案。 但是您必须将其行更改为,

((ButtonObj)->*(ButtonFunc))();

因为 ButtonObj 是指向对象的指针

Others have told you how to do it correctly. But I'm surprised no-one told you this code is actually dangerous:

this->ButtonFunc = &ButtonFunc;

Since ButtonFunc is a parameter, it will go out of scope when the function returns. You are taking its address. You will get a value of type void (object::**ButtonFunc)() (pointer to a pointer to a member function) and assign it to this->ButtonFunc. At the time you would try to use this->ButtonFunc you would try to access the storage of the (now not existing anymore) local parameter, and your program would probably crash.

I agree with Commodore's solution. But you have to change his line to

((ButtonObj)->*(ButtonFunc))();

since ButtonObj is a pointer to object.

趴在窗边数星星i 2024-07-12 06:59:53

在极少数情况下,您碰巧使用 Borland C++Builder 进行开发,并且不介意编写特定于该开发环境的代码(即不能与其他 C++ 编译器一起工作的代码),您可以使用 __closure 关键字。 我发现了一篇关于C++Builder闭包的小文章。 它们主要用于与 Borland VCL 一起使用。

In the rare case that you happen to be developing with Borland C++Builder and don't mind writing code specific to that development environment (that is, code that won't work with other C++ compilers), you can use the __closure keyword. I found a small article about C++Builder closures. They're intended primarily for use with Borland VCL.

睫毛溺水了 2024-07-12 06:59:53

使用标准的面向对象不是会更好吗? 定义一个契约(虚拟类)并在您自己的类中实现它,然后只需传递对您自己的类的引用并让接收者调用契约函数。

使用您的示例(我已将“test2”方法重命名为“buttonAction”):

class ButtonContract
{
  public:
    virtual void buttonAction();
}


class testMenu : public MenuScreen, public virtual ButtonContract
{
  public:
    bool draw;
    MenuButton<testMenu> x;

    testMenu():MenuScreen("testMenu")
    {
      x.SetButton(100,100,TEXT("buttonNormal.png"), 
              TEXT("buttonHover.png"), 
              TEXT("buttonPressed.png"), 
              100, 40, &this);
      draw = false;
    }

    //Implementation of the ButtonContract method!
    void buttonAction()
    {
      draw = true;
    }
};

在接收器方法中,您存储对 ButtonContract 的引用,然后当您想要执行按钮的操作时,只需调用该方法的“buttonAction”方法存储的 ButtonContract 对象。

Would you not be better served to use standard OO. Define a contract (virtual class) and implement that in your own class, then just pass a reference to your own class and let the receiver call the contract function.

Using your example (I've renamed the 'test2' method to 'buttonAction'):

class ButtonContract
{
  public:
    virtual void buttonAction();
}


class testMenu : public MenuScreen, public virtual ButtonContract
{
  public:
    bool draw;
    MenuButton<testMenu> x;

    testMenu():MenuScreen("testMenu")
    {
      x.SetButton(100,100,TEXT("buttonNormal.png"), 
              TEXT("buttonHover.png"), 
              TEXT("buttonPressed.png"), 
              100, 40, &this);
      draw = false;
    }

    //Implementation of the ButtonContract method!
    void buttonAction()
    {
      draw = true;
    }
};

In the receiver method, you store the reference to a ButtonContract, then when you want to perform the button's action just call the 'buttonAction' method of that stored ButtonContract object.

尹雨沫 2024-07-12 06:59:53

对于类似的事情,我强烈推荐 boost::bindboost::function

请参阅 传递并调用成员函数 (boost::bind / boost::功能?)

I'd strongly recommend boost::bind and boost::function for anything like this.

See Pass and call a member function (boost::bind / boost::function?)

谎言月老 2024-07-12 06:59:53

我知道这是一个相当古老的话题。 但是有一种优雅的方法可以用 c++11 来处理这个问题,

#include <functional>

像这样声明你的函数指针,

typedef std::function<int(int,int) > Max;

声明你的函数,你将这个东西传递给它,

void SetHandler(Max Handler);

它,

SetHandler(&some function);

假设你有一个成员函数

class test{
public:
  int GetMax(int a, int b);
...
}

假设你传递一个普通的函数给它,你可以像平常一样使用 您可以使用 std::placeholders 传递您的代码,如下所示

test t;
Max Handler = std::bind(&test::GetMax,&t,std::placeholders::_1,std::placeholders::_2);
some object.SetHandler(Handler);

I know this is a quite old topic. But there is an elegant way to handle this with c++11

#include <functional>

declare your function pointer like this

typedef std::function<int(int,int) > Max;

declare your the function your pass this thing into

void SetHandler(Max Handler);

suppose you pass a normal function to it you can use it like normal

SetHandler(&some function);

suppose you have a member function

class test{
public:
  int GetMax(int a, int b);
...
}

in your code you can pass it using std::placeholders like this

test t;
Max Handler = std::bind(&test::GetMax,&t,std::placeholders::_1,std::placeholders::_2);
some object.SetHandler(Handler);
ペ泪落弦音 2024-07-12 06:59:53

要通过指针调用成员函数,您需要两个东西:指向对象的指针和指向函数的指针。 您在 MenuButton::SetButton() 中需要两者,

template <class object>
void MenuButton::SetButton(int xPos, int yPos, LPCWSTR normalFilePath,
        LPCWSTR hoverFilePath, LPCWSTR pressedFilePath,
        int Width, int Height, object *ButtonObj, void (object::*ButtonFunc)())
{
  BUTTON::SetButton(xPos, yPos, normalFilePath, hoverFilePath, pressedFilePath, Width, Height);

  this->ButtonObj = ButtonObj;
  this->ButtonFunc = ButtonFunc;
}

然后您可以使用两个指针调用该函数:

((ButtonObj)->*(ButtonFunc))();

不要忘记将指向对象的指针传递给 MenuButton::SetButton()代码>:

testMenu::testMenu()
  :MenuScreen("testMenu")
{
  x.SetButton(100,100,TEXT("buttonNormal.png"), TEXT("buttonHover.png"),
        TEXT("buttonPressed.png"), 100, 40, this, test2);
  draw = false;
}

To call a member function by pointer, you need two things: A pointer to the object and a pointer to the function. You need both in MenuButton::SetButton()

template <class object>
void MenuButton::SetButton(int xPos, int yPos, LPCWSTR normalFilePath,
        LPCWSTR hoverFilePath, LPCWSTR pressedFilePath,
        int Width, int Height, object *ButtonObj, void (object::*ButtonFunc)())
{
  BUTTON::SetButton(xPos, yPos, normalFilePath, hoverFilePath, pressedFilePath, Width, Height);

  this->ButtonObj = ButtonObj;
  this->ButtonFunc = ButtonFunc;
}

Then you can invoke the function using both pointers:

((ButtonObj)->*(ButtonFunc))();

Don't forget to pass the pointer to your object to MenuButton::SetButton():

testMenu::testMenu()
  :MenuScreen("testMenu")
{
  x.SetButton(100,100,TEXT("buttonNormal.png"), TEXT("buttonHover.png"),
        TEXT("buttonPressed.png"), 100, 40, this, test2);
  draw = false;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文