Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: pouCZ 19. 12. 2023, 13:03:23
-
Ahoj,
chci se zeptat zda níže uvedený přístup k vytvoření zpětného volání z rodiče na potomka je dobré.
Jde mi o toto: chci mít v rodiči pole (vektor) struktr ve kterých budou registrované funkce pro volání (včetně podmínek kdy se daná funkce má zavolat).
Potomek si potom vytvoří vlastní libovolnou funkci a podmínku za které se tato funkce zavola - toto si zaregistruje (podmínka může být např. periodicky 12s). Rodič potom ve funkci process() zjistí zda podmínka platí a zavolá příslušnou funkci.
Děkuji
#include <iostream>
class BASE_CLASS {
public:
BASE_CLASS() : callbackFce(nullptr) {}
template <typename T>
void registerCallBack(void (T::*callback)()) {
callbackFce = dynamic_cast<void (BASE_CLASS::*)()>(callback);
}
void process() {
if (callbackFce != nullptr) {
(this->*callbackFce)();
}
}
private:
void (BASE_CLASS::*callbackFce)();
};
class FOOO : public BASE_CLASS {
public:
FOOO() : BASE_CLASS() {
registerCallBack(&FOOO::callbackFunction);
}
protected:
void callbackFunction() {
std::cout << "Hello" <<std::endl;
}
};
int main() {
FOOO test;
test.process();
return 0;
}
-
a neni to zbytecne slozite?
rodicovska trida muze mit jen virtualni metodu process.
odvozena trida potomek reimplementuje metodu process a uvnitr se muze spustit cokoliv.
-
Díky za odpověď.
To by samozřejmě šlo, jenže to by pak každý potomek musel implementovat skoro to samé.
Co se týče např. času tak uložit si poslední čas a pak jestli uběhlo už X sekund.... Příjde mi to pak že opakuji zbytečný kód.
Navíc počítám že těch podmínek by pak mohlo být víc.
-
Díky za odpověď.
To by samozřejmě šlo, jenže to by pak každý potomek musel implementovat skoro to samé.
Co se týče např. času tak uložit si poslední čas a pak jestli uběhlo už X sekund.... Příjde mi to pak že opakuji zbytečný kód.
Navíc počítám že těch podmínek by pak mohlo být víc.
tak muzete zaklad/boilerplate implementovat v rodicovi v metode process a rodic muze mit i prazdnou virtualni funkci,
ktera bud ma prazdny vnitrek, nebo je deklarovana treba void specialni_funkce() = 0;
a rodic bude mit v process()
{
...hafo kodu....
specialni_funkce();
}
a potomci uz budou mit jenom neco jineho ve specialni_funkce.
v tride to mas mit zapouzdrene, callback ma smysl, ale tady bych nerekl, ze ma.
-
jinak v c++ se koukni na std::function a lambda.
-
jenže jak bys např. udělal že jeden potomek chce zavolat funkci1() - každou sekundu, funkci2() co 10s a funkci3() co 15s atd ( např. teď píšu potomka co chci aby jednou za 10minut zkontroloval připojená čidla, každé 2minuty reportoval teplotu a co 1s hlídal překročení teploty).
Jenže jiní potomci vůbec časové funkce nepotřebují - nač je mít tedy implementovane v předkovi (sice s prázdným tělem).....A to bych tam měl mít v tom předkovi pro každý čas fnkci? Nebo mít v předkovi pevný počet funkcí na čas a jen proměnnýma vybírat kdy se jaká spouští??
Nevím možná je to tak správně - proto se ptám.
-
jenže jak bys např. udělal že jeden potomek chce zavolat funkci1() - každou sekundu, funkci2() co 10s a funkci3() co 15s atd ( např. teď píšu potomka co chci aby jednou za 10minut zkontroloval připojená čidla, každé 2minuty reportoval teplotu a co 1s hlídal překročení teploty).
Jenže jiní potomci vůbec časové funkce nepotřebují - nač je mít tedy implementovane v předkovi (sice s prázdným tělem).....A to bych tam měl mít v tom předkovi pro každý čas fnkci? Nebo mít v předkovi pevný počet funkcí na čas a jen proměnnýma vybírat kdy se jaká spouští??
Nevím možná je to tak správně - proto se ptám.
rodicovska trida muze treba obsahovat pole (lambda) funkci, vektor pointeru na funkce, vektor std::function nebo nemusis ani pouzit dedeni, ale muzes pouzit template.
od zakladni tridy muzes mit odvozeno vice potomku, jeden muze mit implementaci pro casovace, dalsi potomek nemusi.
spolecnou maji jen metodu process().
-
jenže jak bys např. udělal že jeden potomek chce zavolat funkci1() - každou sekundu, funkci2() co 10s a funkci3() co 15s atd ( např. teď píšu potomka co chci aby jednou za 10minut zkontroloval připojená čidla, každé 2minuty reportoval teplotu a co 1s hlídal překročení teploty).
Jenže jiní potomci vůbec časové funkce nepotřebují - nač je mít tedy implementovane v předkovi (sice s prázdným tělem).....A to bych tam měl mít v tom předkovi pro každý čas fnkci? Nebo mít v předkovi pevný počet funkcí na čas a jen proměnnýma vybírat kdy se jaká spouští??
Moje odpoved neni C++, ale jestli to je embedded vec, tak tohle si rika primo o vyuziti sluzeb RTOS.
V automotive se pouziva OSEK, ktery na toto ma vse potrebne.
(ovsem ne vsude, jedna automobilka ma implementovano v roce 2022 tohle v ECU motoru pomoci nekolika fci obsahujici hejno volani dalsich fci a je to nejak rozdelene na "volej casto" "volej mene casto" "volej jeste mene casteji" ...)
Jestli jsou ty C++ tridy tak odlisne, ze vznikaji subsety virtualnich metod, zavani to trosku spatnym navrhem, ale to jen odhaduji. Chtelo by to asi vice detailu.
-
jenže jak bys např. udělal že jeden potomek chce zavolat funkci1() - každou sekundu, funkci2() co 10s a funkci3() co 15s atd ( např. teď píšu potomka co chci aby jednou za 10minut zkontroloval připojená čidla, každé 2minuty reportoval teplotu a co 1s hlídal překročení teploty).
Jenže jiní potomci vůbec časové funkce nepotřebují - nač je mít tedy implementovane v předkovi (sice s prázdným tělem).....A to bych tam měl mít v tom předkovi pro každý čas fnkci? Nebo mít v předkovi pevný počet funkcí na čas a jen proměnnýma vybírat kdy se jaká spouští??
Moje odpoved neni C++, ale jestli to je embedded vec, tak tohle si rika primo o vyuziti sluzeb RTOS.
V automotive se pouziva OSEK, ktery na toto ma vse potrebne.
(ovsem ne vsude, jedna automobilka ma implementovano v roce 2022 tohle v ECU motoru pomoci nekolika fci obsahujici hejno volani dalsich fci a je to nejak rozdelene na "volej casto" "volej mene casto" "volej jeste mene casteji" ...)
Jestli jsou ty C++ tridy tak odlisne, ze vznikaji subsety virtualnich metod, zavani to trosku spatnym navrhem, ale to jen odhaduji. Chtelo by to asi vice detailu.
tohle jde i v ramci c++ resit tunou ruznych reseni, takze tezko autorovi presne poradit.
-
Proč vlastně chceš použít dědičnost? Přijde mi, že sem se moc nehodí...
Jinak to zní zhruba jako ScheduledExecutorService v Javě ( https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html ), v C++ se bohužel moc nevyznám, ale možná existuje taky něco podobnýho
-
https://www.fluentcpp.com/2018/12/28/timer-cpp/
-
Jedná se o domácí bastl kód - žádné auto-motive nebo nic produkčního.
Tvořím na raspberry pico ovládání žaluzií, ovládání podlahovky a čtení teplot atd.
Cílem bylo vytvořit něco jako možnost potomků si zapnout periodické volání nějakých metod - nic víc.
Pokud to tedy chápu dobře, tak na zmíněném přístupu nic špatně není, ale je moc složitý. Je to tak?
Děkuji za std::function to jsem neznal a dalo by se také použit.
-
Jedná se o domácí bastl kód - žádné auto-motive nebo nic produkčního.
Tvořím na raspberry pico ovládání žaluzií, ovládání podlahovky a čtení teplot atd.
Cílem bylo vytvořit něco jako možnost potomků si zapnout periodické volání nějakých metod - nic víc.
Snad si psal, ze to bude v Rustu ne? Takze zmena na C++, ktere je pro tebe opet moc zlozite? Nechapu.
-
Jedná se o domácí bastl kód - žádné auto-motive nebo nic produkčního.
Tvořím na raspberry pico ovládání žaluzií, ovládání podlahovky a čtení teplot atd.
Cílem bylo vytvořit něco jako možnost potomků si zapnout periodické volání nějakých metod - nic víc.
Pokud to tedy chápu dobře, tak na zmíněném přístupu nic špatně není, ale je moc složitý. Je to tak?
Děkuji za std::function to jsem neznal a dalo by se také použit.
v c/c++ muzes napsat co chces :-)
ale doporucuji to psat co nejjednoduseji/nejpochopitelneji a dokumentovat.
a v dnesni dobe je dobre se drzet metod moderniho c++.
-
Jedná se o domácí bastl kód - žádné auto-motive nebo nic produkčního.
Tvořím na raspberry pico ovládání žaluzií, ovládání podlahovky a čtení teplot atd.
Cílem bylo vytvořit něco jako možnost potomků si zapnout periodické volání nějakých metod - nic víc.
Snad si psal, ze to bude v Rustu ne? Takze zmena na C++, ktere je pro tebe opet moc zlozite? Nechapu.
Možná jsem před Vánoci trochu chorý na mysli ale o Rustu jsem se snad nezmínil....
-
Jedná se o domácí bastl kód - žádné auto-motive nebo nic produkčního.
Tvořím na raspberry pico ovládání žaluzií, ovládání podlahovky a čtení teplot atd.
Cílem bylo vytvořit něco jako možnost potomků si zapnout periodické volání nějakých metod - nic víc.
Pokud to tedy chápu dobře, tak na zmíněném přístupu nic špatně není, ale je moc složitý. Je to tak?
Děkuji za std::function to jsem neznal a dalo by se také použit.
v c/c++ muzes napsat co chces :-)
ale doporucuji to psat co nejjednoduseji/nejpochopitelneji a dokumentovat.
a v dnesni dobe je dobre se drzet metod moderniho c++.
Proto se ptám zda toto je přístup moderního c++ a pokud ne tak jak by to mělo být.
-
Jedná se o domácí bastl kód - žádné auto-motive nebo nic produkčního.
Tvořím na raspberry pico ovládání žaluzií, ovládání podlahovky a čtení teplot atd.
Cílem bylo vytvořit něco jako možnost potomků si zapnout periodické volání nějakých metod - nic víc.
Snad si psal, ze to bude v Rustu ne? Takze zmena na C++, ktere je pro tebe opet moc zlozite? Nechapu.
Možná jsem před Vánoci trochu chorý na mysli ale o Rustu jsem se snad nezmínil....
udelej to v cem chces.
a kdyz se budes chtit ucit novy jazyk tak to pak do nej predelej a nenech si nakecat, ktery to ma byt.
-
Jedná se o domácí bastl kód - žádné auto-motive nebo nic produkčního.
Tvořím na raspberry pico ovládání žaluzií, ovládání podlahovky a čtení teplot atd.
Cílem bylo vytvořit něco jako možnost potomků si zapnout periodické volání nějakých metod - nic víc.
Snad si psal, ze to bude v Rustu ne? Takze zmena na C++, ktere je pro tebe opet moc zlozite? Nechapu.
Možná jsem před Vánoci trochu chorý na mysli ale o Rustu jsem se snad nezmínil....
Zrovana tady tento (https://forum.root.cz/index.php?topic=28293.0) pan chce take ovladat zaluzie na RPi, ale pres CAN bus v Rustu. Ale vidim, ze je to nekdo jiny. Tak pardon a klidne Vanoce ;).
-
Jedná se o domácí bastl kód - žádné auto-motive nebo nic produkčního.
Tvořím na raspberry pico ovládání žaluzií, ovládání podlahovky a čtení teplot atd.
Cílem bylo vytvořit něco jako možnost potomků si zapnout periodické volání nějakých metod - nic víc.
Keby si niekde (github?) dal kod, dalo by sa o tom lepsie diskutovat.
Suhlasim s snugar_i ze toto nevyzera na pripad pre dedicnost. Skus urobit jednu triedu,
ktora poskytuje funkciu volania callbackov, mozno ako singleton, a tie jednotlive casti (ovladanie zaluzii)
si u nej budu registrovat co a kedy potrebuju volat (cez lambdu alebo std::function), pripadne v ktorom threade.
Pouziva sa pri tom finta, ze registrovanie callbacku vracia nieco (ID, pointer) pomocou ktoreho ten callback vies zrusit.
Uz som par rokov nerobil v C++ tak ti nenapisem detaily, skor myslienku.
struct Callback {
int id;
int frequency;
std::function<> callback;
}
class Callbacks {
public:
int registerCallback(int frequency, std::function<> callback) {
int id = findFreeId();
callbacks.push(new Callback(id, frequency, callback);
};
void unregisterCallback(int id) {
// remove Callback with id from callbacks
}
private:
std::vector<Callback> callbacks;
int findFreeId() const {
// find some unused id
}
// zostava napisat ako sa spustaju callbacky...
}
-
A nebylo by mozna jednodusi vyuzit misto callbacku (labda funkci a pod) funktory? Vyhodou je to ze nemusis ziskavat ukazatel na konkretni funkci (nebo metodu) callbacku, a protoze funktor je sam o sobe trida, a do pole muzes ukladat rovnou instance techto trid. Dalsi benefit je v tom, ze muzes do nej primo implmentovat metody, ktere otestuji splneni dane podminky. Trida BASE_CLASS uz pak jednak nepotrebuje vedet detaily o provedeni callbacku a taky uz nepotrebuje zadny polymorfismus pro provedeni dane operace, protoze na vsechno co potrebuje k provedeni metody proccess( ) jednoduse zavola metody funktoru. Ziskas tim taky docela solidni nezavislost pri dalsim rozsirovani kodu, protoze pro kazdou operaci, kterou budes chtit resit callbackem pak naimplementujes novy funktor, ktery "vi" co je potreba udelat a co ma delat, a BASE_CLASS::proccess( ) to uz jen diriguje ;)