Jak napsat odkaz na funkci třídy

Wiring, C++, C, Java, ...
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Odpovědět
PetrB
Příspěvky: 141
Registrován: 20 čer 2018, 13:39
Reputation: 0

Jak napsat odkaz na funkci třídy

Příspěvek od PetrB » 25 čer 2020, 16:19

Ahoj,
zase hledám, jak něco napsat. Tentokrát potřebuji laborovat s odkazem na funkci třídy.
Co chci napsat: mám nějakou obecnou třídu, která má funkci execute a ta si umí zavolat nějakou funkci (s předem jasnými parametry), která ji je předaná v rámci parametrů.
Umím to napsat jako odkaz na statickou metodu:

Kód: Vybrat vše

 typedef bool(*provedNeco)(int vParametr);
 
 class tTrida {
  tTrida() {}
  void execute(provedNeco vCo) {
   if (vCo(5)) {
    Serial.println(F("O.K."));
   }
  }
 }
 
 bool Test(int vParametr) {
  return vParametr==3;
 }
 
 void setup() {
  pObjekt=new tTrida();
  pObjekt->execute(*Test);
 }
Ale pokud by metoda Test měla být součástí třídy, tak mi to napsat nejde.
Někde jsem našel přibližně toto:

Kód: Vybrat vše

class TVolanaTrida; //forward deklarace

typedef  bool(TVolanaTrida::*provedNeco)(int vParametr);

 class tTrida {
  tTrida() {}
  void execute(provedNeco vCo) {
   if (vCo(5)) {
    Serial.println(F("O.K."));
   }
  }
 }

class TVolanaTrida{
 tVolanaTrida(){}
  bool Test(int vParametr) {
  return vParametr==3;
 }
 
 void provedSebe(tTrida vKudy) {
 //Tohle neumím napsat. Asi něco jako
 vKudy.execute(*Test);
 }
}

 void setup() {
  pVolana=new tVolanaTrida();
  pObjekt=new tTrida();
  pVolana->provedSebe(pObjekt);
 }
Otázka je tedy celkem jednoduchá. Jak mám napsat že třída předá jako parametr do nějaké funkce odkaz na svoji metodu? Ta funkce potom tuto metodu vyvolá s nějakými parametry. Jde mi de facto o jakési "call back volání". V jednom objektu mám generální metodu tvořící tabulku v HTML. Jako parametr je jí předán nějaký obecný objekt (třeba seznam teploměrů) a ten jí na zavolání bude přes určitou funkci předávat parametry pro tuto tabulku.

Vím, že si dost vymýšlím, ale jsem zvyklý programovat v jiných jazycích a zde jsou mi zatím nějaké věci dost utajené.

Díky

Pb

Uživatelský avatar
KiLLA
Příspěvky: 29
Registrován: 23 čer 2020, 00:47
Reputation: 0

Re: Jak napsat odkaz na funkci třídy

Příspěvek od KiLLA » 02 črc 2020, 15:53

..jestli to dobře chápu, pomůže ti zjištění, že pointery na funkce musej bejt statický, a můžeš si předávat dynamicky pointer na staickej pointer, pokud je to potřeba.. 8-)

PetrB
Příspěvky: 141
Registrován: 20 čer 2018, 13:39
Reputation: 0

Re: Jak napsat odkaz na funkci třídy

Příspěvek od PetrB » 02 črc 2020, 17:26

Můžeš mi hodit příklad?
V Delphi to napsat umím:

Kód: Vybrat vše

Type
       TFunkce = Function (vParam : Integer) : string of object;
       
      TPracuje = Class
                         constructor Create;   //tento konstruktor je prázdný, nebudu to rozepisovat
                         procedure Execute(VCo : TFunkce;vParam : Integer);
                       End;
                       
      TCeka = Class
                     pHodnota : Integer;
                    constructor Create(vParam : Integer);
                    Function MneVolej(vParam : Integer) : String;
                   End;                      
                   
procedure TPracuje.Execute(VCo : TFunkce;vParam : Integer);
 Begin
  Writeln(VCo(vParam));  //Vyvolej metodu VCo, předej jí parametr vParam a výsledek vytiskni
 End;
          
constructor TCeka.create(vParam : Integer);
 Begin
  pHodnota:=vParam;
 End;
                        
Function TCeka.MneVolej(vParam : Integer) : String;
 Begin
  Result:=IntToStr(vParam+pHodnota);  //Převeď parametr na text
 End;                  
 
Var
     pracuje : TPracuje;
     ceka : TCeka;
     ceka1 : TCeka;     
 Begin
  pracuje:=TPracuje.Create;   //Vytvoř objekty
  ceka:=TCeka.Create(0);
  ceka1:=TCeka.Create(1);
  ...
   pracuje.execute(ceka.MneVolej,1);   //Volej funkci prvního objektu
   pracuje.execute(ceka1.MneVolej,2);//Volej funkci druhého objektu
  ...
 End;
Uměl by si mi to přepsat pro arduino?
Jde o to, že objekt TPracuje v rámci metody Execute volá metody jiného objektu. No a ten TCeka mu ji poskytuje.
V tuto chvíli nemám žádný konkrétní příklad, spíše mne zajímá, jak se to v Arduinu napíše (pokud to jde).

Díky

Uživatelský avatar
KiLLA
Příspěvky: 29
Registrován: 23 čer 2020, 00:47
Reputation: 0

Re: Jak napsat odkaz na funkci třídy

Příspěvek od KiLLA » 03 črc 2020, 00:24

trochu sem to pochopil špatně, koukám :lol:
v delphi sem nikdy nic nepsal :cry:

ale z posledních řádků mezi begin a end je patrný co to má cca dělat..

u cpp podobnou funkčnost umožňuje friend class, kdy lze použít i private members ze zpřátelený třídy

Kód: Vybrat vše

class TCeka {
  friend class TPracuje;
};
horší to je se spouštěním timhle způsobem, zjednodušil bych to..
tohle de dosadit i jako vlastnost třídy.. 8-)

Kód: Vybrat vše

typedef void (* functionPointer) ();
functionPointer pracuje;
pracuje = ceka;
pracuje();
ale možná by bylo jednodušší volat funkci přímo :mrgreen:

PetrB
Příspěvky: 141
Registrován: 20 čer 2018, 13:39
Reputation: 0

Re: Jak napsat odkaz na funkci třídy

Příspěvek od PetrB » 03 črc 2020, 08:18

Díky, výhledově se s tím pokusím nějak popasovat.
Jde mi o to, že mám nějaký objekt, který se má obecně starat o web server a obsluhovat jednotlivé stránky, které má v sobě registrované. Tam je to jednoduché, každá stránka má svoji metodu "execute", která ji vygeneruje a web server ji volá.
Pak mám ovšem obecný "senzor", který si nějak načítá svoje hodnoty a ty potom umí "poslat" na stránku. Senzor by těch metod pro posílání mohl mít více (např. podle charakteru stránky a pod.) a jde o to, že by si ten senzor zaregistroval svoji metodu pro konkrétní stránku a ta by ji potom v rámci svého "execute" vykonala. Dopředu tedy nevím, jaká to bude metoda, ale znám její parametry. V maximalistickém případě by mohla mít stránka z těch metod dokonce pole a cyklicky je volat.
Ale to byl jenom takový nápad.
Každopádně díky za typ.

Pb

Uživatelský avatar
KiLLA
Příspěvky: 29
Registrován: 23 čer 2020, 00:47
Reputation: 0

Re: Jak napsat odkaz na funkci třídy

Příspěvek od KiLLA » 03 črc 2020, 10:03

opravená provní část kódu 8-)

Kód: Vybrat vše

typedef bool(*provedNeco)(int vParametr);

class tTrida {
  public:
    tTrida() {}
    int16_t execute(provedNeco vCo) {
      if (vCo(5) == true) { // testnem to
        Serial.println(F("O.K."));
      }
      else {
        Serial.println(F("Error."));
      }
    }
}; // <-- chyběl středníček

bool Test(int vParametr) {
  Serial.println(F("Test run."));
  return vParametr == 5;
}

void setup() {
  Serial.begin(115200); // bez toho to nevim nevim
  //pObjekt = new tTrida(); // error :-D
  tTrida pObjekt; // radši takhle

  pObjekt.execute(*Test); // a takto
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.println(F("Nemám rád češtinu v kódu."));
  delay(1000);
}

Uživatelský avatar
KiLLA
Příspěvky: 29
Registrován: 23 čer 2020, 00:47
Reputation: 0

Re: Jak napsat odkaz na funkci třídy

Příspěvek od KiLLA » 03 črc 2020, 12:46

..když sem tu druhou část přepsal, aby to odpovídalo, házelo mi to pořád chyby.. mrknu na to o víkendu, ale problém je v tom, že pointer na member funkci je jinej, než na fci bez třídy.. i když to mám napsaný (nejspíš) dobře, arduino ide to odmítá zkompilovat.. :lol:

Uživatelský avatar
KiLLA
Příspěvky: 29
Registrován: 23 čer 2020, 00:47
Reputation: 0

Re: Jak napsat odkaz na funkci třídy

Příspěvek od KiLLA » 03 črc 2020, 13:38

https://stackoverflow.com/questions/860 ... s-function
arduino ide odmítá zkompilovat i toto..

https://www.codeguru.com/cpp/cpp/articl ... nction.htm
https://isocpp.org/wiki/faq/pointers-to-members
trochu víc do detailů..

na web z 8266 bych použil něco klasickýho, tohle je zbytečně komplikovaný -> blbě by se to udržovalo a když s tim pak pohneš, třeba bys to i přepisoval, protože to kuli x,y,z nepude.. výstupy ze senzoru nacpat do struct, tu jako parametr k funkcím..

může si s sebou nýst i pointer na odpovídající funkci..

Kód: Vybrat vše

typedef void (* functionPointer) ();

struct Result
{
  uint32_t value = 0;  //

  functionPointer function;
};

Result result; // global

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  // Result result; // local

  result.function = hehe;
  result.function(); //<------

  test(&result);

  delay(1000);
}

void hehe() {
  Serial.println(F("lololololo"));
}

void test(Result* res) {
  Serial.print(F("result value: ")); Serial.println(res->value);
  res->value++;
}

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 15 hostů