Как передать функцию-член в конструктор базового класса? - PullRequest
0 голосов
/ 30 октября 2019

У меня есть структура класса, которую я хочу использовать, и я хочу использовать функцию производного класса для передачи в качестве аргумента конструктора в базовый класс. Я не могу найти правильный синтаксис для него (новичок в C:))

Это базовый класс, который я использую, и у него есть конструктор с функцией обратного вызова:

class SPortSensor {
        public:
            SPortSensor(sensorData (*pCallback)(SPortSensor*));
            sensorData getValue();
        private:
            sensorData (*getData)(SPortSensor*);
    };

Этопроизводный класс, который реализует функцию обратного вызова внутри класса (pCallback), поэтому он имеет другой конструктор и функцию-член, которую необходимо передать конструктору базового класса:

    class SimpleSensor : public SPortSensor {
        public: 
            SimpleSensor(int id);
            long value;
        private:
            int _id;
            sensorData pCallback(SPortSensor*);
    };

Этот заголовок прекрасно компилируется. Единственная ошибка, которую я вижу, заключается в реализации конструктора SimpleSensor. Я не могу найти правильный синтаксис для этого:

sensorData SimpleSensor::pCallback(SPortSensor* sensor) {
   ...
}

SimpleSensor::SimpleSensor(int id) : SPortSensor(pCallback) {
  _id = id;
}

Поиск в Google этой проблемы не сильно помог, так как я, вероятно, не использую правильные поисковые слова и не достаточно разбираюсь в c ++ (яC # парень).

Ответы [ 3 ]

1 голос
/ 30 октября 2019

Циркулярная ссылка пахнет так, как будто могут быть некоторые общие проблемы с владением.

Но, одним из способов обхода вашего тупика является использование std::function<sensorData(SPortSensor*)> вместо указателей на функции. Затем инициализируйте базовый класс с помощью лямбды, указывающей на себя:

SimpleSensor(int id) : SPortSensor([this](SPortSensor* sps) { return pCallback(sps); }) { }

Я не могу в хорошем сознательном оправдании этому, но он не взорвался, когда я попробовал. Одно предостережение: SimpleSensor не будет инициализирован при вызове базового конструктора, поэтому SPortSensor не может вызвать лямбду в своем собственном конструкторе.

0 голосов
/ 30 октября 2019

Так что я думаю, что сложность (проблема?) Заключалась в том, чтобы попытаться сделать это с помощью нескольких строк кода. Я просто переключился на полиморфизм с абстрактным классом, чтобы упростить вещи.

Абстрактная база:

    class SPortSensor {
        public:
            void (*valueSend)(void);
            virtual sensorData getData () = 0;
    };

2 класса реализации:

class CustomSPortSensor : public SPortSensor {
        public:
            CustomSPortSensor(sensorData (*callback)(CustomSPortSensor*));
        private:
            sensorData (*_callback)(CustomSPortSensor*);

        virtual sensorData getData(){
            return _callback(this);
        }
    };

    class SimpleSPortSensor : public SPortSensor {
        public: 
            SimpleSPortSensor(int id);
            long value;
        private:
            int _id;

        virtual sensorData getData(){
            sensorData data;
            data.sensorId = _id;
            data.value = value;
            return data;
        }
    };

Теперь это работает, как и ожидалось. очень прост в использовании и понимании (использование реализации должно быть максимально читабельным).

Теперь я хочу, чтобы реализация виртуальных функций была только в .cpp вместо .h .... ...

0 голосов
/ 30 октября 2019

Обратные вызовы обычно происходят между различными объектами. Одно из решений состоит в том, чтобы отличать использование метода производного класса после конструктора (например, в методе init?) И объявить метод как виртуальный.

#include <iostream>

struct sensorData {
    double val = 0;
};

class SPortSensor {
public:
    virtual sensorData getValue() {
        std::cout << "Base class\n";
        sensorData sd;
        return sd;
    }
};

class SimpleSensor : public SPortSensor {
public: 
    long value;
    SimpleSensor(int id): id(id) {
    }
    virtual sensorData getValue() {
        std::cout << "Derived class\n";
        sensorData sd;
        return sd;
    }
private:
    int id;
};


int main() {
    SPortSensor base;
    SimpleSensor derived(1);
    base.getValue();
    derived.getValue();
    SPortSensor* derivedPtr = new SimpleSensor(2);
    derivedPtr->getValue();
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...