| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Список функций класса. |
| Автор: OlegIT 7.7.2014, 07:56 |
| В классе имеются несколько однотипных функций. Как сделать список из этих функций в QList или vector? |
| Автор: Lukkoye 7.7.2014, 08:57 | ||
http://rextester.com/XFBRA12764
Первый способ работает быстрее. Но менее гибкий. Создается указатель на функцию-член, в котором фигурирует имя класса, что делает невозможным хранить в одном списке указатели на методы разных классов. Второй способ более мощный, гибкий - создание делегата. Делегат - это особый класс функторов (std::function), способный осуществлять запуск свободной функции или функции члена, без необходимости "помнить" к какому классу относится функция-член. Грубо говоря, std::function это что-то вроде кютешных слотов-сигналов, вот только защита времени компиляции и работает на порядок быстрее. |
| Автор: OlegIT 7.7.2014, 11:05 |
| Спасибо. Как я понимаю Ваша ссылка на ресурс, где можно запускать свой код, вставляя его в окно редактора. Так? |
| Автор: OlegIT 8.7.2014, 11:14 |
| Протестировал Ваш код в Visual Studio и в Qt5.3. Ошибки такие, компилятор не знает, что есть такое emplace_back (хотя внутри vector он есть) и bind. И на функцию launch() по полной выругался. Поместил в буфер функции с помощью push_back, но вызвать их не получается. У меня другой ещё вопрос. Это всё мне нужно для предотвращения зацикливания, мои однотипные функции могут вызываться последовательно и вернутся к первоначальной функции. Что бы этого избежать, я создаю буфер из этих функций, а потом, в основном цикле программы, выполняю вызов функций из этого буфера. Но при вызове может оказаться, что буфер функций пополнился. Не будет тут проблемы? Может по другому это можно сделать? |
| Автор: OlegIT 8.7.2014, 14:24 |
Включу. Мне не очень нравится моя идея по защите, тут ещё вопрос как/где запустить отработку созданного буфера. Может есть другие, более грамотные решения? |
| Автор: NoviceF 8.7.2014, 14:57 |
Это вопрос из области многопоточности. В случае если к структуре данных имеют доступ два и более потоков, нужно синхронизировать доступ к ней при помощи примитивов синхронизации, таких как мьютексы, rwlock, и т.п. То есть, перед тем, как ты начинаешь вызывать функции коллекции, ты захватываешь мьютекс, и ни один другой поток не сможет получить доступ к этой коллекции, пока ты мьютекс не освободишь. Все потоки, что будут пытаться внести изменения в коллекцию или выполнить чтение из неё, будут блокироваться на вызове функции захвата мьютекса, и разблокируются (по одному) только тогда, когда поток, совершающий обход коллекции мьютекс освободит. |
| Автор: Lukkoye 8.7.2014, 19:25 | ||||
Вижал студия из коробки умеет std::function начиная с версии 10 Насчет Qt: 1. Если вы используете систему сборки QMake, пропишите в файле сценария сборки имя_вашего_проекта.pro следующий ключ: QMAKE_CXXFLAGS += -std=gnu++1y либо QMAKE_CXXFLAGS += -std=c++0x 1. Если вы используете систему сборки Сmake, пропишите в файле сценария сборки CMakeLists.txt set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++1y ") либо set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") Данный ключ активирует поддержку нововведений в стандарте языка. По поводу "зацикливаний":
Разумеется будут. Каноничную реализацию можно подглядеть рассматривая устройство какой нибудь "EventSystem". Если вкратце: есть отдельный класс, называемый "Eventsystem ", который хранит внутри себя несколько списков: 1. Желающие добавиться. 2. Желающие удалиться. Этот список представляет собой пару: <делегат, вкл/выкл> Eventsystem в цикле бежит по рабочему циклу, и запускает одного за другим делегаты. Допустим, запуск делегата приводит в действие функцию, которая пытается добавить в Eventsystem новый делегат - он добавляется в список "желающих добавиться". Рабочий же список остается без изменений. Если же запуск делегата приводит в действие функцию, которая напротив, пытается удалить делегат - он просто помечается как "выкл", и Eventsystem знает, что его использовать нельзя. Больше он уже не будет запущен. Если же претендент на удаление обнаружится в списке "желающих добавиться" - можно удалить оттуда сразу же. После того, как весь рабочий цикл завершился, только тогда Eventsystem добавляет в рабочий список новеньких, а так же выбрасывает всех тех, кто помечен, как "выкл". Кроме того, поскольку запуски делегатов происходят в одном единственном месте: в Eventsystem, там удобно ставить защиту для многопоточного режима, а так же легко пропасти - был ли один и тот же делегат вызван дважды. То бишь, легко отловить факт рекурсивных вызовов, и зацикливания. |
| Автор: OlegIT 9.7.2014, 11:16 |
| Спасибо за разъяснения. С делегатами и двумя очередями понятно. Не понятно где выполнять вызовы, обработку списка и где "Eventsystem добавляет в рабочий список новеньких"? |