Вопрос, с которым вы столкнулись, заключается в передаче указателя на член функции объекта в функцию, ожидающую глобальный указатель на функцию. В вашем случае есть динамический список объектов, для каждого из которых необходимо передать функцию-обработчик. В C# это решается с помощью делегатов, но в C++ аналогичного механизма нет в стандартной библиотеке для версий компиляторов, предшествующих C++11.
Для решения вашей задачи можно использовать следующий подход:
Создать вспомогательную функцию, которая будет принимать указатель на объект и указатель на член-функцию, которую нужно выполнить.
Использовать эту вспомогательную функцию для создания "обертки" вокруг члена-функции, которая может быть передана в функцию, ожидающую глобальный указатель на функцию.
Вот пример кода, который демонстрирует данный подход:
#include <iostream>
#include <list>
#include <functional>
// Определение класса с виртуальной функцией-обработчиком
class BaseTask {
public:
virtual void task(float x, float y) = 0;
};
// Реализация класса, наследующегося от BaseTask
class ListeningTask : public BaseTask {
public:
void task(float x, float y) override {
std::cout << "Обработчик объекта: " << this << ", параметры: " << x << ", " << y << std::endl;
}
};
// Вспомогательная функция для создания обертки вокруг члена-функции
void taskWrapper(BaseTask* task, float x, float y) {
task->task(x, y);
}
// Класс, который будет использоваться для подписки на обработчики
class RegisterTask {
public:
void subscribe(std::function<void(float, float)> callback) {
callback(1.0f, 2.0f);
}
};
// Главная функция
int main() {
RegisterTask registerTask;
std::list<ListeningTask> listeningTasks;
// Создание списка объектов
for (int i = 0; i < 10; ++i) {
listeningTasks.push_back(ListeningTask());
}
// Создание оберток для каждого обработчика
for (auto& task : listeningTasks) {
std::function<void(float, float)> callback = std::bind(taskWrapper, &task, std::placeholders::_1, std::placeholders::_2);
registerTask.subscribe(callback);
}
return 0;
}
В данном примере мы создаем вспомогательную функцию taskWrapper, которая принимает указатель на объект BaseTask и вызывает его метод task. Затем, используя функтор std::bind, мы создаем обертку вокруг этого метода для каждого объекта в списке listeningTasks. Полученные обертки передаются в функцию subscribe класса RegisterTask.
Обратите внимание, что для работы данного примера требуется поддержка std::function и std::bind, которые присутствуют в Visual Studio 2010, но могут быть использованы в namespace tr1 вместо std.
Этот подход позволяет передать указатель на член-функцию объекта в функцию, которая ожидает глобальный указатель на функцию, и при этом сохранить связь с конкретным объектом.
Передача указателя на член функции объекта в функцию, предназначенную для глобальных обработчиков, с использованием вспомогательной функции и обертки, для работы в MSVC2010.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.