为什么在SFML C++项目中传递对象和函数指针时收到访问冲突错误?

wbrvyc0a  于 2023-06-07  发布在  其他
关注(0)|答案(1)|浏览(95)

我目前正在学习c++,我正在使用SFML/TGUI开发我的第一个游戏。我试过创建一个函数来创建一个按钮,当按下按钮时,它会调用一个函数。为了使按钮创建器更智能、更多版本,我将其设置为接受一个对象指针和一个函数指针作为参数。当按钮被按下时,我希望它能够从传递给它的对象调用成员函数。还应该指出的是,我让它工作了一段时间,但后来我改变了一些东西,现在它不工作。
在main.cpp中,我创建了一个gui和一个指向这个gui的指针。然后我将指针传递到我的Utility类,它由静态变量和函数组成:

//Create gui object
tgui::GuiSFML gui{ window };

//Create pointer to gui object
tgui::GuiSFML* guiPointer = &gui;

//Pass guiPointer into Utility class
Utility::setup_getGuiPointer(guiPointer);

这就是我的实用程序类中的内容:

//Static gui pointer in Utility
static tgui::GuiSFML* guiPointer;

//Passes gui pointer from main into Utility
static void Utility::setup_getGuiPointer(tgui::GuiSFML* passedGuiPointer)
{
    guiPointer = passedGuiPointer;
}

我的实用程序类中的创建按钮函数如下所示:

//Takes arguments: ObjectPtr, FunctionPtr, Size, Pos and Text to create button
template<typename Class>
inline tgui::Button::Ptr& Utility::u_createButton(Class* object, void(Class::* functionPointer)(tgui::GuiSFML* guiPointer, tgui::Button::Ptr& button), tgui::Layout2d size, tgui::Layout2d position, std::string buttonText)
{
        //Creates the button
    tgui::Button::Ptr button = tgui::Button::create(buttonText);

        //Sets size and position
    button->setSize(size);
    button->setPosition(position);

        //Adds button to gui
    guiPointer->add(button);

        //Sets onPress on the button to call the passed function from the passed objects,
        //passing the gui pointer and button pointer into this function.
    button->onPress([&]() { (object->*functionPointer)(guiPointer, button); });

        //Returns button pointer if it's needed before onPress.
    return button;
}

现在,我可以在任何类中使用以下行创建一个自定义按钮:

Utility::u_createButton(this, &ClassName::FunctionName, size, position, text;

我在我的一个类中创建了一个按钮,我传递一个指针的函数是:

void ClassName::FunctionName(tgui::GuiSFML* guiPointer, tgui::Button::Ptr& button)
{
    std::cout << "Button Pressed" << std::endl;

        //The reson behind the passed arguments is so that the function itself can delete
        //the button after use if needed using the following line:
    //guiPointer->remove(button);
}

当我运行它时,它会创建一个按钮,但当我按下它时会出现以下错误:

Unhandled exception at 0x85EEB600 in GUI_SFML_Template.exe: 0xC0000005: Access violation executing location 0x00000000.

The current stack frame was not found in a loaded module. Source cannot be shown for this location.

我不明白为什么我会得到这个错误,尽管我相信这与我的对象和函数在没有正确访问的情况下试图写入gui有关。如果有人能帮助我,我将不胜感激。

a8jjtwal

a8jjtwal1#

你的lambda是通过引用捕获的,当按钮被按下时,它捕获引用的所有局部变量都会导致未定义的行为,因为局部变量将超出范围。您应该按值捕获:

button->onPress([object, functionPointer, guiPointer, button]() { (object->*functionPointer)(guiPointer, button); });

一般来说,通过引用捕获所有对象的lambda表达式只在声明它们的函数中使用是安全的,不应该长期存储。

相关问题