C ++ указатель на функцию-член - PullRequest
0 голосов
/ 20 сентября 2018

Я пишу небольшую платформу для OpenGL API с использованием C ++ с 2 классами:

  • GameObject (Компонентная архитектура):

    • Добавить MeshRenderer в качестве компонента,
    • Добавить материал как компонент.
  • Материал:

    • Обрабатывает все данные шейдера и присоединяется как компонент к GameObject.
    • Содержит личное: void RegisterComponent (RCUpdateCallback & funcPtr);
  • MeshRenderer:

    • Обрабатывает назначенные данные сетки (VAO, VBO, EBO и т. Д.)

      // routine to handle shader change  
      Contains private: void MeshRenderer::UpdateMaterial();  
      

Теперь во время выполнения, если пользователь хочет изменить шейдер материала, класс сетки должен быть обновлен также с новыми данными.Итак, я пытаюсь сохранить функцию обратного вызова MeshRenderer::UpdateMaterial(SG_EUpdate& flag) -> внутри класса материала.

Вот псевдокод для него:

/* Register the callback here for this mesh's Update method inside the constructor of the mesh*/
SGMeshRenderer::SGMeshRenderer( SGMeshFilter mesh_copy, SG_PTRS<SGMaterial> mat )
{
    SGUUIDGenerator::instance().Create( uuid );
    material = mat;
    material->RegisterComponent( this, &SGRenderer::UpdateMaterial );
}

/* Register Function inside the mesh class for storing all the callback */
void SGMaterial::RegisterComponent( SGRenderer* const object, RCUpdateMethod method )
{
    map_renderCompCallbacks.insert( MapRCUCallbacks::value_type( object, method ) );
}

/*   Whenever New Shader is set, material calls all the meshes UpdateMethod */
void SGMaterial::SetShader( SG_PTRS<Shader> const shader )
{
    activeShader = shader;
    std::cout << "START OF FUNCTION : " << __FUNCTION__ << std::endl;
    std::cout << "Material name : " << name << " id : " << uuid << "Active Shader : " << activeShader->shaderProgramName << std::endl;
    std::cout << "END OF FUNCTION : " << __FUNCTION__ << std::endl;
    // Generate Shader data
    SGMaterialManager::instance().Create( uuid, *activeShader );
    // Update all the RendererComponents using this material ( ReBuild- VAOs)
    for( auto it = map_renderCompCallbacks.begin(); it != map_renderCompCallbacks.end(); it++ )
    {
        // using Object reference to call the stored pointer.
        // If we have the object reference we can do it->first->UpdateMethod() directly.
        ( it->first->*it->second )( SG_EUpdateFlag::MaterialUpdate );
    }
}

Проблема в том, что я могу сохранитьметод в качестве обратного вызова, но при вызове метода из класса Material мне также нужна ссылка на объект сетки для вызова соответствующего указателя функции.

Примерно так: MeshRenderer::*StoredFuncPointer(args);

Теперь я не вижу смысла хранить обратные вызовы, если мы хотим отправить ссылку на объект, я могу просто вызвать весь метод по ссылке.

Так какой смысл иметь указатели на элементы, если нам нужноссылка на объект?

1 Ответ

0 голосов
/ 20 сентября 2018

Смысл наличия указателя на член в том, что вы можете использовать его с любым объектом, а не только с заранее определенным.

Указатель на член больше похож на индекс массива, чем на указатель;если вы храните число k, вы можете извлечь элемент k: th любого массива, если вы также знаете, из какого массива его следует извлечь.

Если вы хотите вызвать функцию впредопределенный объект, тогда указатель на член - это не то, что вам нужно - вы, вероятно, хотите std::function и std::bind.

Очень простой пример:

struct A
{
    A(const std::string& nm) : name(nm){}
    void f() { cout << name << " f\n";}
    void g() { cout << name << " g\n";}
    std::string name;
};

int main()
{
    A a("a");
    A b("b");
    using fun = std::function<void()>;
    std::vector<fun> fns = {std::bind(&A::f, a),
                            std::bind(&A::g, a),
                            std::bind(&A::f, b)};

    for (auto& f: fns)
        f();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...