Правильный способ вызова функции-члена через QHash с указателями на функции-члены

У меня есть класс сервера, который обрабатывает данные QJsonObject и обрабатывает их в соответствии с набором ключей в данных.

На данный момент я использую большой оператор if-then-else, чтобы решить, что делать следующим образом:

const QString action = jsonObject.value(KEY_ACTION).toString();
if (action == SOME_ACTION) {
    // do something
} else if (action == SOME_OTHER_ACTION) {
    // do something else
}

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

Я подумал о том, чтобы обрабатывать данные в разных функциях и иметь QHash с соответствующим указателем функции на соответствующую функцию для каждого действия, например:

В конструкторе:

const QHash<QString, void(Server::*)(const QJsonObject &)> processFunctionsMap {
    { SOME_ACTION, &Server::processSomeAction },
    { SOME_OTHER_ACTION, &Server::processSomeOtherAction }
}

И соответствующие функции:

void Server::processSomeAction(const QJsonObject &data)
{
    ...
}

а затем вызвать соответствующую функцию:

if (! processFunctionsMap.contains(action)) {
    // Catch this case
}
(this->*processFunctionsMap.value(action))(jsonObject);

Кажется, это работает, но я не профессионал в С++, поэтому мой вопрос в том, правильный ли это способ сделать это.


person Tobias Leupold    schedule 12.08.2019    source источник


Ответы (1)


Ваш подход разумен, но вы изменили сценарий отсутствия совпадений с выполнения блока else (возможно, вообще ничего не делая) на мгновенное неопределенное поведение.

Вам нужно отделить поиск хеша от вызова, чтобы вы могли вставить проверку на успешный поиск между ними. Со стандартными коллекциями С++ (std::map, которое является красно-черным деревом, std::unordered_map, которое является хеш-таблицей), это будет вызов find(key), который возвращает итератор... вы сравниваете его с map.end() и очень следите за тем, чтобы не разыменовывались, если они равны. QHash или любая другая нестандартная хеш-таблица, несомненно, даст что-то подобное.

person Ben Voigt    schedule 12.08.2019
comment
Спасибо, что подтвердили, что все в порядке :-) Извините за неполный пример, я отредактирую свой код, чтобы избежать неопределенного поведения. - person Tobias Leupold; 12.08.2019