2013-06-19 9 views
-1

Я хочу связать функцию-член с std::function<void(void)>. Я слышал, что функции-члены принимают один дополнительный параметр, который является указателем экземпляра. Поэтому я вызываю std::bind(&Class::Function, this, parameter), но когда я выполняю объект функции, он выдает ошибку времени выполнения.Выполнение связанных std :: function throws std :: bad_function_call

Необработанное исключение в в 0x748D4B32 в application.exe: Microsoft C++ исключение: станд :: bad_function_call в ячейку памяти 0x0114F4E8.

Параметр является указателем на один из моих собственных struct. Как я поступаю неправильно? Какая дополнительная информация вам нужна?

Обновление: Вот мой код.

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(); 
    } 
}; 
+2

Как насчет того, чтобы показать нам код, который выбрасывает это исключение? Укажите строки, в которых вы назначаете указатель функции-члена функции 'std :: function'. 'bad_function_call' вызывается при попытке вызвать' std :: function', у которого нет цели, поэтому код привязки имеет значение. – Praetorian

+0

@Praetorian Я раньше не использовал 'std :: bind', поэтому я не знал, какой код важен. И в моем проекте много кода. Но, благодаря вашему комментарию, я мог бы предоставить необходимые фрагменты своего кода. Я обновил свой вопрос. – danijar

+1

'for (auto i: pass)' будет копировать каждый элемент 'pass' в' i' - у 'Pass' есть назначенный конструктор копии? – Casey

ответ

1

В приведенных выше замечаниях указано несколько различных вопросов. Для того, чтобы решить эти, попробуйте сделать следующие изменения в коде:

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 
} 
1
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... 
} 
+0

Приятная идея использовать индекс. – danijar