Arrow
1 мая 2017 г. 1:00

Callback функции

Callback функции, STL

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

Вот код:

ReverseString.h

#ifndef REVERSESTRING_H
#define REVERSESTRING_H

#include <map>
#include <string>
using namespace std;

class ReverseString
{
public:
    ReverseString();
    ~ReverseString();
    // Получить буквенный шифр и перекодировать в цифровой
    void decode(const string data);
    // Установка функции обратного вызова
    void setCallBackFunc(void (*func) (string data));

private:
    // Список численных значений для букв
    map<char, int> m_map;
    // Возвращаемая строка
    string m_string;
    // Указатель на функцию обратного вызова (возвращает цифровой шифр)
    void (*callbackfunction) (string data);
};

#endif // REVERSESTRING_H

ReverseString.cpp

#include "reversestring.h"

ReverseString::ReverseString()
{
    // Перевод букв (шеснадцатеричные значения) в десятичные
    m_map = {{'A', 10 }, {'B', 11}, {'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}};
}

ReverseString::~ReverseString()
{
    // Очистить данные
    m_map.clear();
    m_string.clear();
}

void ReverseString::decode(const string data)
{
    // Получить буквенный шифр и перекодировать в цифровой
    m_string.clear();
    // Прекодировка
    for (int i = 0; i < m_string.length(); ++i) {
        m_string += m_map.at(data.at(i));
    }
    // Вызвать функцию обратного вызова для возврата
    // кодированной строки
    callbackfunction(m_string);
}

void ReverseString::setCallBackFunc(void (*func) (string data))
{
    // Установка функции обратного вызова
    callbackfunction = func;
}

main.cpp

#include <QCoreApplication>
#include <string>
#include <iostream>
using namespace std;

#include "reversestring.h"

void codeStringView(string data)
{
    // Вывести кодированную строку
    // полученную от callback функции
    cout << data << endl;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    string data;

    cout << "Enter string:" << endl;

    cin >> data;

    ReverseString *codeString = new ReverseString();

    // Установить функцию обратного вызова
    codeString->setCallBackFunc(codeStringView);

    codeString->decode(data);

    getchar();

    return a.exec();
}

Код написал от фонаря :) только для понимания как работает Callback функция.

2
Вопрос задан по статьеQt/C++ - Урок 026. Применение CallBack функции

Вам это нравится? Поделитесь в социальных сетях!

7
Evgenii Legotckoi
  • 1 мая 2017 г. 12:06

Думаю, что здесь всё правильно сделано кроме одного единственного момента.

Функция, которая передаётся в качестве CallBack функции должна быть статической. Не статические функции не получится передать в качестве обычных CallBack функций.

static void codeStringView(string data)
{
    // Вывести кодированную строку
    // полученную от callback функции
    cout << data << endl;
}
    Arrow
    • 2 мая 2017 г. 14:35

    Программа запускается но результат не выводит. После ввода символа (А, В, С ... ) и нажатия Enter каретка переходит на новую строку и ничего не происходит. Нет ни ответа ни ошибки.

      Arrow
      • 2 мая 2017 г. 14:37

      Она просто продолжает работать - реагирует на все нажатия клавиш.

        Evgenii Legotckoi
        • 2 мая 2017 г. 21:18

        А дело оказалось вовсе не CallBack. Ошибка в следующем коде:

        Было

        for (int i = 0; i < m_string.length(); ++i) {
            m_string += m_map.at(data.at(i));
        }

        Стало

        for (int i = 0; i < data.length(); ++i) {
            m_string.append(to_string(m_map.at(data.at(i))));
        }

        Ошибки следующие:

        1. Проверка длины не той переменной. m_string.length() всегда будет равен нулю. Вы же его очищаете перед циклом.
        2. Добавлять к str::string нужно именно std::string. При попытке добавления данных переменной целочисленного типа - эта переменная воспринимается как код символа, а не как число 10, например.
        3. Поэтому нужно делать преобразование кода через std::to_string()
          Arrow
          • 2 мая 2017 г. 23:13

          Спасибо!

          Концентрировал внимание на CallBack и понадеялся, что все остальное написал правильно. :)

          Теперь программа вылетает и пишет ошибку:

          Запускается C:\Users\admin\Desktop\CallBackFunc\bild\Debug\debug\CallBackFunc.exe... Error - RtlWerpReportException failed with status code :-1073741823. Will try to launch the process directly C:\Users\admin\Desktop\CallBackFunc\bild\Debug\debug\CallBackFunc.exe завершился с кодом -1073741819

          По отладчику вылетает на строке:

          callbackfunction(m_string);

          С сообщением: Segmentation fault.

            Evgenii Legotckoi
            • 2 мая 2017 г. 23:18
            • Ответ был помечен как решение.

            Ну как бы странно, что вылетает с Segmentation fault. Вот мой код.

            main.cpp
            #include <QCoreApplication>
            #include <string>
            #include <iostream>
            #include <QDebug>
            
            using namespace std;
            
            #include "reversestring.h"
            
            void codeStringView(string data)
            {
                // Вывести кодированную строку
                // полученную от callback функции
                cout << data << endl;
            }
            
            int main(int argc, char *argv[])
            {
                QCoreApplication a(argc, argv);
            
                string data;
            
                cout << "Enter string:" << endl;
            
                cin >> data;
            
                ReverseString *codeString = new ReverseString();
            
                // Установить функцию обратного вызова
                codeString->setCallBackFunc(codeStringView);
            
                codeString->decode(data);
            
                getchar();
            
                return a.exec();
            }
            reversestring.h
            #ifndef REVERSESTRING_H
            #define REVERSESTRING_H
            
            #include <map>
            #include <string>
            using namespace std;
            
            class ReverseString
            {
            public:
                ReverseString();
                ~ReverseString();
                // Получить буквенный шифр и перекодировать в цифровой
                void decode(const string data);
                // Установка функции обратного вызова
                void setCallBackFunc(void (*func) (string data));
            
            private:
                // Список численных значений для букв
                map<char, int> m_map;
                // Возвращаемая строка
                string m_string;
                // Указатель на функцию обратного вызова (возвращает цифровой шифр)
                void (*callbackfunction) (string data);
            };
            
            #endif // REVERSESTRING_H
            reversestring.cpp
            #include "reversestring.h"
            
            ReverseString::ReverseString()
            {
                // Перевод букв (шеснадцатеричные значения) в десятичные
                m_map = {{'A', 10 }, {'B', 11}, {'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}};
            }
            
            ReverseString::~ReverseString()
            {
                // Очистить данные
                m_map.clear();
                m_string.clear();
            }
            
            void ReverseString::decode(const string data)
            {
                // Получить буквенный шифр и перекодировать в цифровой
                m_string.clear();
                // Прекодировка
                for (int i = 0; i < data.length(); ++i) {
                    m_string.append(to_string(m_map.at(data.at(i))));
                }
                // Вызвать функцию обратного вызова для возврата
                // кодированной строки
                callbackfunction(m_string);
            }
            
            void ReverseString::setCallBackFunc(void (*func) (string data))
            {
                // Установка функции обратного вызова
                callbackfunction = func;
            }
              Arrow
              • 2 мая 2017 г. 23:29

              Понял, спасибо!

              Вылетало потому, что было так:

              codeString->decode(data);
              codeString->setCallBackFunc(codeStringView);

              А нужно так:

              codeString->setCallBackFunc(codeStringView);
              codeString->decode(data);

              Туплю.

                Комментарии

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