Ошибка: указатель на связанную функцию может использоваться только для вызова функции

Вопрос: Я пытался назначить указатель функции (класса) функции-члена (другого класса) следующим образом: --- Game.h --- #ifndef GAME_H #define GAME_H #include "Screen.h" class Game { private: void (*HandleCurrentScreen)(); public: void SetScreen(const Screen& newScreen); }; #endif --- Game.cpp --- #include "Game.h" #include "Screen.h" void Game::SetScreen(const Screen& newScreen) { HandleCurrentScreen = newScreen.Handle; //Produces the error } --- Screen.h

Вопрос:

Я пытался назначить указатель функции (класса) функции-члена (другого класса) следующим образом:

— Game.h — #ifndef GAME_H #define GAME_H #include «Screen.h» class Game { private: void (*HandleCurrentScreen)(); public: void SetScreen(const Screen& newScreen); }; #endif — Game.cpp — #include «Game.h» #include «Screen.h» void Game::SetScreen(const Screen& newScreen) { HandleCurrentScreen = newScreen.Handle; //Produces the error } — Screen.h — #ifndef SCREEN_H #define SCREEN_H class Screen { public: void Handle(); }; #endif — Screen.cpp — #include «Screen.h» void Screen::Handle() { … }

Я получаю эту ошибку:

ошибка C3867: “Экран :: Ручка”: список отсутствующих аргументов функции; use ‘& Screen :: Handle’ для создания указателя на элемент

Кажется, что это нормально, если HandleCurrentScreen указывает на функцию, которая также определена в классе Game. Я искал других людей с этой проблемой, но ни один из них, похоже, не был в таких случаях.

Решение, которое может работать, выглядит примерно так:

Screen* p_currentScreen; void Game::SetScreen(const Screen& newScreen) { p_currentScreen = &newScreen; }

а затем вместо вызова HandleCurrentScreen я могу вызвать p_currentScreen->Handle(), но для меня это кажется немного менее эффективным.

Что я могу сделать, чтобы исправить это? Должен ли я просто использовать указатель на класс вместо указателя на функцию?

Любые советы приветствуются.

Лучший ответ:

Ваша ошибка говорит вам, что делать:

Screen::Handle’: function call missing argument list; use ‘&Screen::Handle

Вы должны написать это как:

void Game::SetScreen(const Screen& newScreen) { HandleCurrentScreen = &Screen::Handle; }

Он будет работать только в том случае, если newScreen::handle является статической функцией. Но в этом случае вы можете инициализировать его во время компиляции. В противном случае HandleCurrentScreen должен быть указателем на функцию-член (PTMF), объявленную как:

void (Screen::*HandleCurrentScreen)();

Теперь, чтобы вызвать функцию из PTMF, вам нужен объект функции. Это делает ваше второе решение лучше.

Другим вариантом является std :: bind:

class Game { private: std::function<void()> HandleCurrentScreen; public: void SetScreen(const Screen& newScreen) { HandleCurrentScreen = std::bind(&Screen::Handle, &newScreen); } }; Ответ №1

std::bind создан для решения такой проблемы:

// — Game.h — #ifndef GAME_H #define GAME_H #include «Screen.h» #include <functional> class Game { private: std::function<void ()> HandleCurrentScreen; public: void SetScreen(const Screen& newScreen); }; #endif // — Game.cc — #include «Game.h» #include «Screen.h» void Game::SetScreen(const Screen& newScreen){ HandleCurrentScreen = std::bind( &Screen::Handle, newScreen); }

Однако, поскольку вашему Game классу нужна только функция, возможно, лучший дизайн, чтобы полностью исключить класс Screen из определения Game и передать его непосредственно:

#include <functional> class Game { public: typedef std::function<void ()> ScreenHandler; private: ScreenHandler HandleCurrentScreen; public: void SetHandle(const ScreenHandler &handle); }; #endif // — Game.cc — #include «Game.h» void Game::SetHandle(const ScreenHandler &handle){ HandleCurrentScreen = handle; }

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

Оцените статью
Добавить комментарий