Вызов метода класса из другого метода этого же класса
- Войдите на сайт для отправки комментариев
Втр, 29/05/2018 - 22:57
Здравствуйте, уперся в такую проблемку, нужно в одном из методов класса использовать другой метод. Но синтаксиса я не знаю и найти как то не вышло, наверно не так формулирую. Я так понимаю должно использоватся что то вроде self или this?
class buu {
int a;
void f1() {
a++;
}
void f2() {
f1(); // здесь использовать метод f1
a++;
}
};
vasya00,можно.Но лучше через внешний обработчик.
#258
Выходт ошибка
error: invalid use of non-static member function
vasya00. Все же упрямитесь . Хорошо читайте серьезную литературу. Могут еще метры начать писать вам тяжелый для вашего понимания текст.
Даа, тут у меня проблема в другом оказывается, это с библиотекой TTimerList.h от DetSimen, не обрабатывается
Если f1 метод класса. Тут скорее вопрос к DetSimen
Спасибо!
Так создайте одиночную функцию-посредник.
void f(){/*а здесь вызов конкретный метод конкретного класса */}
Дак вот дело в том что тут посредник вне класса не поможет, надо как раз чтобы внутри класса это было, без конкретной привязки к экземпляру. Если я правильно выразил мысль..
vasya00. значит вы модель системы не проработали. Ведь методы обработки класса вывести из класса и все. Так что лучше прорабатывайте систему, а не усложняйте, то что не надо усложнять.
Дак вот дело в том что тут посредник вне класса не поможет, надо как раз чтобы внутри класса это было, без конкретной привязки к экземпляру. Если я правильно выразил мысль..
У Деда сделана привязка функции, для того, чтобы метод класса могла быть привязана к дедовской либе - эта метод должен быть объявлен с модификатором static. Однако, статические члены класса ничего не знают о конкретном инстансе класса, соответственно, там никакие this не помогут.
Обычно проблема решается передачей дополнительного параметра (в вашем случае - как раз this) в вызывающую сторону. Вызывающая сторона сохраняет этот параметр, и передаёт вам. В общем случае выглядит это так, применительно к вашему примеру:
typedef void (*PCallback)(void* param); class Caller { public: void callMe(PCallback callback, void* param) { callback(param); } }; Caller caller; class SomeClass { public: static void calle(void* param) { SomeClass* ptr = (SomeClass* ) param; ptr->doSomething(); } void doSomething() { Serial.print("this is "); Serial.println((uint16_t) this); // do the dirty job here! } void bind() { caller.callMe(calle, this); } }; SomeClass some; SomeClass some2; some.bind(); some2.bind();Надеюсь, понятно, что происходит: класс SomeClass имеет общий для всех экземпляров статический метод, который ничего не знает про this. Метод bind передаёт вызывающей стороне (экземпляр класса Caller) указатель на функцию и указатель на экземпляр класса SomeClass. Внутри метода callMe класса Caller просто идёт вызов статического метода calle класса SomeClass, при этом ему передаётся параметр (this, который передал вызывающей стороне экземпляр класса SomeClass). Внутри метода doSomething просто выводится значение this, чтобы убедиться, что метод вызывается для разных экземпляров класса.
Как-то так.
Даа, тут у меня проблема в другом оказывается, это с библиотекой TTimerList.h от DetSimen, не обрабатывается
Если f1 метод класса. Тут скорее вопрос к DetSimen
DetSimen тут не поможет. Метод класса нельзя передавать по ссылке, как обычную функцию, поскольку для каждого экземпляра указатель на этот метод будет свой. Единственное исключение - статические методы, их передавать по ссылке можно, о чем вам компилятор и говорит.
Хотите более подробно - вбейте сообщение компилятора в Гугль и почитайте ссылки - например на Stackoverflow (на английском)
/**/ class Cl_AAA { protected: byte num; public: Cl_AAA(byte n): num(n) {} void viev() { Serial.println(num); } void viev(Cl_AAA *p) { p->viev(); } }; //------------------------------------- Cl_AAA AAA(/*номер*/1); Cl_AAA BBB(/*номер*/2); //------------------------------------- void setup() { Serial.begin(9600); AAA.viev(); AAA.viev(&BBB); } void loop() { } /**/Или так
/**/ class Cl_AAA { protected: byte num; public: Cl_AAA(byte n): num(n) {} void viev() { Serial.println(num); } void viev(Cl_AAA &p) { p.viev(); } }; //------------------------------------- Cl_AAA AAA(/*номер*/1); Cl_AAA BBB(/*номер*/2); //------------------------------------- void setup() { Serial.begin(9600); AAA.viev(); AAA.viev(BBB); } void loop() { } /**/Или так, чтобы уж наверняка ))
/**/ class Cl_AAA { protected: byte num; public: Cl_AAA(byte n): num(n) {} void viev() { Serial.println(num); } static void viev(Cl_AAA &p) { p.viev(); } }; //------------------------------------- Cl_AAA AAA(/*номер*/1); Cl_AAA BBB(/*номер*/2); //------------------------------------- void setup() { Serial.begin(9600); AAA.viev(); AAA.viev(BBB); BBB.viev(BBB); BBB.viev(); Cl_AAA::viev(BBB); // Cl_AAA::viev(); // а так уже не получится } void loop() { } /**/Ты не в скаску попал, в С++ делегатов нет нихрена, а указатели на методы это настолько тонкая вещь, што спицца можно.
Давай сделаем простейший отомат управления освещением.
TAnalogSensor - это класс любого аналогового датчика, в данном случае - фоторезистора
TDevice - класс исполнительного механизма, в данном случае - реле включения освещения
static const int LIGHT_ON_VALUE = 500; // значение, при котором свет включается static const int LIGHT_OFF_VALUE = 600; // значение, при котором свет выключается extern TTimerList TimerList; TAnalogSensor PhotoSensor(A0); // на А0 у нас фоторезистор TDevice LightRelay(9); // на 9 пине исполнительное устройство, реле для лампы освещения THandle hSensorRead; // хэндл таймера чтения // функция вызывается таймером раз в секунду void tmrSensorRead(void) { PhotoSensor.Read(); // читаем раз в секунду фоторезистор. Если значение изменится более // чем на Gap попугаев - вызовется evtPhotoChange } // функция вызывается самим классом TAnalogSensor, изнутри, если значение на нём изменилось на Gap попугаев void evtPhotoChange(int avalue) { // если темно и не включено - включаем if ((avalue < LIGHT_ON_VALUE) && (LightRelay.getState() == enDeviceState::Off)) LightRelay.On(); // если светло и включено - выключаем if ((avalue > LIGHT_OFF_VALUE) && (LightRelay.getState() == enDeviceState::On)) LightRelay.Off(); } void setup() { PhotoSensor.Gap = 10; // гистерезис чтения - 10 попугаев PhotoSensor.OnValueChange = evtPhotoChange; // назначаем фоторезистору функцию, которая будет вызываться // при любом изменении освещенности на величину больше Gap TimerList.Add(1000, tmrSensorRead); // взводим таймер для чтения фоторезистора раз в секунду } void loop() { // тут даже писать ничо не надо, автомат управления освещением работает сам по себе :) }Как видишь, таймеры и с классами прекрасно себя чуствуют, чего и мне желают, после вчерашнева.
DetSimen, да но в вашем случае tmrSensorRead не метод класса. Поэтому по таймеру без проблем вызывается. Если например есть множество объектов класса датчиков, и у каждого свое значение PhotoSensor со своим пином подключения и другие свойства, в идеале, нужно методом класса, в "общем виде" включать таймер для каждого конкретного объекта свой, со всеми его свойствами, возможно меняя их при этом. Статический метод тут тоже не подойдет, так как нужен индивидуальный для каждого экземпляра.
В моем случае задумка такая:
#include "TTimerList.h" extern TTimerList TimerList; THandle hOnceTimer; class Swich { public: const uint32_t signal_length = 100; uint8_t lamp_pin; void use (); void swich (); void swich_finish(); }; void Swich::use () { // работа с выключателем, проверка состояний всяких датчиков // много всего но в конечном итоге: swich(); // по определенным условиям переключение выключателя в другое состояние } void Swich::swich (void) { // метод переключения реализует импульс длительностью signal_length hOnceTimer = TimerList.Add(signal_length, swich_finish); // взводим таймер digitalWrite(lamp_pin, HIGH); // подаем сигнал на включение } void Swich::swich_finish(void) { digitalWrite(lamp_pin, LOW); // выключаем сигнал TimerList.Delete(hOnceTimer); // удаляем таймер } Swich sw1; Swich sw2; Swich sw3; void setup() { } void loop() { sw1.use(); sw2.use(); sw3.use(); }DIYMan, как я понял предлогает то что нужно, пытаюсь разобраться...
Акей, канешна. Изучай.
Но в твоей архитектуре - проблема.
DetSimen, возможно, что заметили что не так? Это пока набросок так скажем, в конструкторе будут читаться переменные из конфига, и наверно стоит перейти на опрос датчиков с фиксированным интервалом.. И с вариантом DIYMan, не разобрался, создавать отдельный свой таймер для каждого объекта класса не выйдет хотябы потому что hOnceTimer глобальный и один да и вообще не выходит никак. Думаю может зайти с другой стороны как то..
В моей поделке можно одновременно завести 12 таймеров на разные интервалы (для UNO), для Mega - 16.
Да ваша библиотека крута, обязательно буду использовать ее. За нее отдельное спасибо! И всетаки можно как то организовать использования ее внутри класса, с разными объектами? Или стоит вынести этот таймер "за класс"? Так и не могу толком понять..