Узнать какой экземпляр класса вызвал функцию

vasya00
Offline
Зарегистрирован: 30.05.2016

Здравствуйте, подскажите, пожалуйста, как бы изящнее реализовать задумку.

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

По всему проще всего было реализовать эту функцию f1 как метод класса, тут и переменные все будут. Но это не возможно, так как работаю с таймером уважаемого DetSimen и внутри класса его работа сопряжена с непреодолимыми для меня трудностями. На данном этапе, я наплодил лишних переменных на входе f1 в которые каждый экземпляр класса при выполнении f1 отправляет свои данные. Но было бы гораздо красивее, если не рализовать f1 как метод класса, то хотябы использовать конкретные переменные вызвавшего f1 объекта.

sadman41
Offline
Зарегистрирован: 19.10.2016
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017
без примера кода и внятного описания, что ты хочешь - гадание бессмысленно. 

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


// обьявления

THandle hSensorsRead;

void tmrSensorsRead(void) {
	SendMessage(msg_ReadSensor); // посылаем сообщение "Читать сенсоры"
}

// настройка в setup()

void setup() {

	hSensorsRead = TimerList.Add(tmrSensorsRead, 2000); // раз в 2 секунды срабатывает tmrSensorsRead

}

// в loop ловим сообщения и вызывает абрабоччики

void loop()
{
	if (NOT MessageList.Availiable()) return;

	TMessage msg = MessageList.GetMessage();

	switch (msg.Message)
	{
	case msg_ReadSensor: {
		BMP280.Read();			// читаем температуру
		SmokeSensor.Read();		// читаем даччик дыма 
		break;
	}
	case msg_TempChanged: {
		DisplayTemp(msg.LoParam); // если температура изменилась - вывести ее на экранчег
		break;
	}

	case msg_SmokeHigh: {
		SetAppState(TAppState::SmokeDetected);  // тут включается вентилятор
		break;
	}

	case msg_SmokeLow: {
		SetAppState(TAppState::NoSmoke);		// тут выключается вентилятор
		break;
	}

.

.
}
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

либо, в f1 передавать указатель на конкретный экземпляр, как правильно сказал sadman, через this.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

vasya00 пишет:
Есть класс с рядом свойств и методов, создается ряд экземпляров этого класса, которые в свою очередь вызывают функцию f1, хотелось бы внутри этой функции f1 понять какой именно из экземпляров класса вызвал ее, и в зависимости от этого работать с переменными именно этого экземпляра.
Похоже вы теорию провтыкали. 1 - если функция это метод класса, то разумеется она привязана к конкретному представителю, а если 2- внешняя то уже каждый преставитель вызывает свою функцию по своему указателю. Если же общая , то 

/**/
class Cl_AAA;//<- предварительное объявление
void total(Cl_AAA *sender);//<- предварительное объявление

class Cl_AAA {
  public:
    Cl_AAA(const char *n): name(n) {}
    const char *name;
    void viev() {
      total(this);
    }
};
void total(Cl_AAA *sender) {
  Serial.println(sender->name);
}
//--------------------------------
Cl_AAA AAA1("AAA1");
Cl_AAA AAA2("AAA2");
//--------------------------------
void setup() {
  Serial.begin(9600);
  AAA1.viev();
  AAA2.viev();
}

void loop() {

}

 

vasya00
Offline
Зарегистрирован: 30.05.2016

Суть задачи была в работе с однотипными наборами датчиков и выключателей, их очень удобно бы было представить как объекты класса, и все бы ничего, но нужно посылать на выключатели импульс, который я отсчитываю таймером,

#include "TTimerList.h"
extern TTimerList TimerList;
THandle hOnceTimer;
class Swich {
  public: const uint8_t signal_length = 100; // длительность импульса на включение
  uint8_t lamp_pin; // пин для подачи импульса на включение
  void chek ();
  void start_impulse ();
  void stop_impulse();
};
  void Swich::chek () { // опрос всяких датчиков
    // принятие решения на включение
    start_impulse(); // и в конечном итоге нужно отправить импульс на включение длительностью signal_length = 100
  }
  void Swich::start_impulse (void) { // метод реализует подачу импульса длительностью signal_length = 100
    hOnceTimer = TimerList.Add(signal_length, stop_impulse); // взводим таймер на выполнение stop_impulse через 100 мс
    digitalWrite(lamp_pin, HIGH); // начинаем импульс
  }
  void Swich::stop_impulse(void) {
    digitalWrite(lamp_pin, LOW); // выключаем сигнал
    TimerList.Delete(hOnceTimer); // удаляем таймер
  }
Swich sw0(0); // создаем экземпляры класса и передаем им номера пинов на которые они должны передавать импульсы
Swich sw1(1);
Swich sw2(2);
void setup() {
 }
Swich::Swich(uint8_t light_pin) { // в конструкторе
  pinMode(lamp_pin, INPUT_PULLUP); // определяем как вход пин для подачи управляющего импульса
} 
void loop() { // последовательно пробегаемся по всем объектам
  sw0.chek();
  sw1.chek();
  sw2.chek(); 
}

Такое решение мне кажется логичным простым и понятным. Хотя и пришлось разбить на 2 метода, начала подачи импульса и его окончание. Красивее придумать не смог.

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ex vasya00, если было бы так просто , то и смысла в моих темах не было. Так что попробуйте эти варианты.

http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-ch...

http://arduino.ru/forum/programmirovanie/tsifrovye-avtomaty-v-klassakh-p...

Или ищите еще варианты решений.