Я хочу привязать функцию-член к std::function<void(void)>
, Я слышал, что функции-члены принимают один дополнительный параметр, который является указателем экземпляра. Поэтому я звоню std::bind(&Class::Function, this, parameter)
но когда я выполняю объект функции, он выдает ошибку во время выполнения.
Необработанное исключение в 0x748D4B32 в Application.exe: Microsoft C ++
исключение: std :: bad_function_call в ячейке памяти 0x0114F4E8.
Параметр является указателем на один из моих struct
s. Как я делаю не так? Какая дополнительная информация вам нужна?
Обновление: вот мой код.
class ModuleRenderer
{
struct Pass{ std::function<void()> Function; /* many more members... */ };
std::vector<std::pair<std::string, Pass>> passes;
enum Drawfunc{ FORMS, SKY, LIGHTS, QUAD, SCREEN };
void AddPass(std::string Name, Drawfunc Function)
{
Pass pass;
// set some of the members
// ...
passes.push_back(std::make_pair(Name, pass));
Pass *pointer = &(passes.back().second);
switch (Function)
{
case FORMS:
pointer->Function = std::bind(&ModuleRenderer::DrawForms, this, pointer);
break;
// analogeously for the other cases
// ...
}
}
void DrawForms(Pass *pass)
{
// ...
}
// is called consecutively after adding all passes
void Update()
{
for(auto i : passes)
// some initializing based on members of pass
i.Function();
}
};
В комментариях выше было отмечено несколько разных проблем. Чтобы устранить их, попробуйте внести следующие изменения в код:
struct Pass{ std::function<void(Pass *)> Function; /* ... */ };
// ...
case FORMS:
pointer->Function =
std::bind(&ModuleRenderer::DrawForms, this, std::placeholders::_1);
break;
Не связывайте Pass *
на вызов функции только что, потому что, как @molbdnilo указывает, что указатель станет недействительным при вызове AddPass()
несколько раз, и вектор изменяется.
Так как std::function
сейчас занимает Pass *
Вам нужно указать правильный указатель при его вызове.
void Update()
{
for(auto& i : passes) { // <-- take a reference, don't copy
// some initializing based on members of pass
i.Function( &i ); // pass Pass * to the function
}
passes.push_back(std::make_pair(Name, pass));
Pass *pointer = &(passes.back().second);
Тот pointer
станет недействительным, когда вы позже push_back
и вектор растет.
Вы можете вообще избегать указателей и передавать указатель соответствующего объекта вместо указателя.
pointer->Function = std::bind(&ModuleRenderer::DrawForms, this, passes.size() - 1);
// ...
void DrawForms(size_t i)
{
Pass& pass = passes[i].second;
// Handle as before...
}