Инициализация экземпляра класса в другом классе
- Войдите на сайт для отправки комментариев
Втр, 29/01/2019 - 08:33
Собсна не получается создать класс на основе двух других. Каким боком вызывать конструкторы этих родительских классов в дочернем? Перебрал несколько пришедших в голову вариантов, ответ компилятора один: no matching function for call to 'InputDev::InputDev()'.
typedef unsigned long dword;
class InputDev {
public:
InputDev(int pin) {
_pin = pin;
pinMode(_pin, INPUT_PULLUP);
_oldSt = active();
}
bool active(void) {
return (digitalRead(_pin) == LOW);
}
bool rise(void) {
_state = active();
_ret = _state && !_oldSt;
delay(5);
_ret &= active();
if (_ret) _oldSt = _state;
return _ret;
}
bool fall(void) {
_state = active();
_ret = _oldSt && !_state;
delay(5);
_ret &= !active();
if (_ret) _oldSt = _state;
return _ret;
}
private:
bool _oldSt, _state, _ret;
int _pin;
};
class OutputDev {
public:
OutputDev(int pin) {
_pin = pin;
pinMode(_pin, OUTPUT);
digitalWrite(_pin, LOW);
}
void set(bool val) {
digitalWrite(_pin, val ? HIGH:LOW);
}
private:
int _pin;
};
class BiDirect {
public:
BiDirect(int inPin, int outPin) {
_inPin = inPin;
_outPin = outPin;
_inObj(inPin);
_outObj(_outPin);
}
bool set(bool val) {
_outObj.set(val);
return (_inObj.active() == val);
}
bool active(void) {
return _inObj.active();
}
bool rise(void) {
return _inObj.rise();
}
bool fall(void) {
return _inObj.fall();
}
private:
int _inPin;
int _outPin;
InputDev _inObj;
OutputDev _outObj;
};
classBiDirect {49public:50BiDirect(intinPin,intoutPin) {51_inPin = inPin;52_outPin = outPin;53_inObj = new InputDev(inPin);54_outObj = new OutputDev(_outPin);55}56boolset(boolval) {57_outObj.set(val);58return(_inObj.active() == val);59}60boolactive(void) {61return_inObj.active();62}63boolrise(void) {64return_inObj.rise();65}66boolfall(void) {67return_inObj.fall();68}69private:70int_inPin;71int_outPin;72InputDev *_inObj;73OutputDev *_outObj;74};иначе - никаг
request for member 'set' in '((BiDirect*)this)->BiDirect::_outObj', which is of pointer type 'OutputDev*' (maybe you meant to use '->' ?)
в строке 57
ну так это ж теперь указатели, и обращайся с ними как с указателями, через ->
каоче, либо так
_outObj->set(val);либо так(*_outObj).set(val);и не забудь тогда деструктор в обьемлющем классе прописать. И лучше всего - виртуальный, на всякий случай.
Большое спасибо добрый человек. Теперь ведь переменные с пинами
int _inPin; int _outPin;больше не нужны я так понимаю. Просто иницируем объкеты прямо в дочернем конструкторе и всё?
class BiDirect { public: BiDirect(int inPin, int outPin) { //_inPin = inPin; //_outPin = outPin; _inObj = new InputDev(inPin); _outObj = new OutputDev(outPin); }естесственно. Пусь оне сами свои пины хранят.
А зачем мне деструктор? У меня обьекты классов что дочернего что родительских "вечные" ))
А зачем мне деструктор? У меня обьекты классов что дочернего что родительских "вечные" ))
Ну.... иногда, случаеца, что это не так. С++ лжив и непредсказуем :)
Можно подробней?
подробней, только в книшках.
Просто поверь и сделай деструктор. если он никогда не понадобица, канпилятор его выкинет.
Ещё хочу создать объект для датчика удара. Что я здесь делаю не так?
class Shock { public: Shock() { pinMode(2, INPUT_PULLUP); pinMode(3, INPUT_PULLUP); _st = 0; } void reset() { _st = 0; attachInterrupt(0, hi, FALLING); attachInterrupt(1, lo, FALLING); } void disable() { detachInterrupt(0); detachInterrupt(1); } byte state() { if (_st == 1) for (dword _begin = millis(); (millis() - _begin) < 100;) if (_st > 1) return 2; if (_st > 2) _st = 2; return _st; } private: static volatile byte _st; static void hi() { _st = 2; detachInterrupt(0); } static void lo() { _st |= 1; detachInterrupt(1); } };sketch/hw.h:92: undefined reference to `Shock::_st'
Каким боком вызывать конструкторы этих родительских классов в дочернем?
Кто Вам сказал, что он у Вас дочерний? Это два независимых класса. Никакого отношения к дочернему не имеют.
Ну, как работать с указателями Вам уже показали. Если же хотите сделать так, как было у Вас (без указателей), то тут есть два варианта (вернее, вариантов больше, но простых два).
1. Инициализируйте члены перед выполнением конструктора. Для этого, в скетче из стартового сообщения, вместо строк №№ 50-55 пишите
BiDirect(int inPin, int outPin) : _inObj(inPin), _outObj(outPin) { _inPin = inPin; _outPin = outPin; }и всё будет.
2. Заведите у InputDev/OuputDev коснтуктор по умолчанию, а нынешнюю инициализацию перенесите в init. Т.е. заводите конструктор InputDev(){}. Также заводите метод void Init(int inPin) {_pin = _inPin; } и используете этот Init для инициализации.
Первое проще, по-моему.
class Cl_AAA { protected: byte data; public: Cl_AAA (byte d): data(d) {} }; class Cl_BBB { protected: Cl_AAA AAA1,AAA2; public: Cl_BBB (): AAA1(5),AAA2(6) {} }; //------------- Cl_BBB BBB; //--------------------- void setup() { } void loop() { }Такое будет работать?
class InputDev { public: InputDev(int pin) { _pin = pin; pinMode(_pin, INPUT_PULLUP); _oldSt = active(); } bool active(void) { return (digitalRead(_pin) == LOW); } bool rise(void) { _state = active(); _ret = !_oldSt && _state; delay(5); } bool fall(void) { _state = active(); _ret = _oldSt && !_state; delay(5); _ret &= !active(); if (_ret) _oldSt = _state; return _ret; } private: bool _oldSt, _state, _ret; int _pin; }; class OutputDev { public: OutputDev(int pin) { _pin = pin; pinMode(_pin, OUTPUT); digitalWrite(_pin, LOW); } void set(bool val) { digitalWrite(_pin, val ? HIGH:LOW); } private: int _pin; }; class BiDirect: public Input, Output { public: BiDirect(int inPin, int outPin) : InputDev(inPin), OutputDev(outPin) { } bool set(bool val) { OutputDev::set(val); return (active() == val); };Такое будет работать?
Что или кто мешает самому запустить и посмотреть?
Конечно, не будет.
Мешает отсутствие ардуинки под рукой. Наследую два класса с перекрытием одного метода <set> и конструктора. Что не правильно?
Зачем ардуинка? Скомпилировать и посмотреть на ошибки компиляции можно и без неё.
Например, что означают слова Input, Output в строке № 43? Таких классов в программе нет, а что эти слова тогда там делают?
Упс.. извиняюсь, не всё переобозвал, пытался сохранить прежние имена для ясности. Компилируется без ошибок. Вобщем вот:
class Input { public: Input(int pin) { _pin = pin; pinMode(_pin, INPUT_PULLUP); _old = active(); } bool active(void) { byte _cntr; do { _cntr = 0; for (byte _i = 1; _i <= 5; _i++) _cntr += (int)digitalRead(_pin); } while ((_cntr > 0) && (_cntr < 5)); return(_cntr == 0); } bool rise(void) { bool _state = active(); bool _ret = _state && !_old; _old = _state; return _ret; } bool fall(void) { bool _state = active(); bool _ret = !_state && _old; _old = _state; return _ret; } private: bool _old; int _pin; }; class Output { public: Output(int pin) { _pin = pin; pinMode(_pin, OUTPUT); digitalWrite(_pin, LOW); } void set(bool val) { digitalWrite(_pin, val ? HIGH:LOW); _state = val; _actual = false; } void pulse(dword timeout) { _begin = millis(); _timeout = timeout; _actual = true; } void processing() { if (_actual) { bool _timely = (millis() - _begin) < _timeout; if (_timely && !_state) { digitalWrite(_pin, HIGH); _state = true;} if (!_timely && _state) { digitalWrite(_pin, LOW); _state = false; _actual = false; } } } private: int _pin; dword _begin = 0; dword _timeout = 0; bool _actual = false; bool _state = false; }; class InOut : public Input, Output { public: InOut(int inPin, int outPin) : Input(inPin), Output(outPin) { } bool set(bool val) { Output::set(val); return (active() == val); } };Ну, явный ляп Вы исправили, а будет ди корректно работать, запустите - посмотрите. Откуда мне знать, если я даже не знаю, что она должна по задумке делать. Запустите, посмотрите, будут вопросы - спросите.
Хотел бы узнать, наследование правильно сделал, класс BiDirect описан корректно? Бедет ли наследовать все методы родителей? Корректно ли создаст их экземпляры при "созданни себя"? Корректно ли заменил метод <set>?
Делаю такое впервые, поэтому успешная компиляцтя ессено ничего не гарантирует. В интернетах есть только примеры наследования одного класса, но про "два в одном" ничего не нашёл. Интересно мнение опытных.
У Вас терминология непонятная. То у Вас посторонние классы - дочерние, то при наследовани создаются экземпляры.
Как создавать экземпляры я Вам написал в посте #13 - надеюсь, Вы его читали.
А здесь создаётся оди экземпляр класса, у которого два родителя. Конструкторы родителей на превый взгляд вызываются нормально.
Терминология как и понимание синтаксиса хромает к сожалению ))) Задача такая:
К пинам подключены "устройства", часть - "контролируемые", которые только читаем, чать "управляемые" в которые только пишем , часть "IO" в которые по одному пину пишем из другого читаем. При этом нужно иметь возможность отслеживать фронты, спады на входах, фильтровать "дребезг" переходных состояний, "писать в выход" импульсы произвольной длинны. Поскольку логика работы со всеми этими устройствами довольно однотипнае, решил глянуть в сторону классов (куда никогда до этого не глядел), иначе основной код превращается в сущий хаос и неразбериху. Вот такакя вот задача. Надеюсь понятно выразился )
vlad072. Вы должны отличать наследование и просто втавки в класс. Вот в классе к примеру переменая int. И скорее нет необходимости ее наследовать с какого-то мифического класса переменных.