C++ funktiopointteriongelma

Viestiketju alueella 'Ohjelmointi' , aloittaja Occurrence, 18.10.2021.

  1. Occurrence

    Rekisteröitynyt:
    23.06.2007
    Viestejä:
    839
    Jos minulla on luokka A jonka sisällä on function void b();
    jotain tähän tapaan...
    class A
    {
    public:
    void b();

    void (*test)();
    };


    Haluan nyt tuon pointterin tuohon functioon niin että voi sijoittaa sen functio-osoittimeen joka on määritelty
    void (*test)(); luokan sisällä

    test = ????;

    Ongelma on siinä että tuossa pitäisi varmaan olla tyyppimuunnos mutta funktiopointterin tyyppimuunnos on jotain mikä on uutta itselle.
     
  2. Photiou

    Rekisteröitynyt:
    23.11.2005
    Viestejä:
    938
    Meniskö näin, jos ymmärsin oikein:
    class A
    {
    public:
    void b();

    void (A::*test)();
    }

    A obj;
    obj.test = &A::b;
     
  3. Occurrence

    Rekisteröitynyt:
    23.06.2007
    Viestejä:
    839
    Sen function osoite pitäisi olla muotoa "void (*test)();" jotta sitä voisin käyttää callbackkinä. Mikään muu ei mene kääntäjästä läpi.

    &A::b on eri muotoa.
     
    Viimeksi muokattu: 18.10.2021
  4. Photiou

    Rekisteröitynyt:
    23.11.2005
    Viestejä:
    938
    Pointter jäsenfunktioon != pointteri funktioon eli onnistuisi noin jos b esim. staattinen. Muutenhan jäsenfunktio kaipaa oliota kutsuttaessa.
    Tämmöisellä testasin gcc:llä:
    #include <iostream>

    class A {
    public:
    static void c() { std::cout << "A::c()" << std::endl; };
    void b() { std::cout << "A::b()" << std::endl; };

    void (A::*test)();
    void (*test2)();
    void callTest() { (this->*test)(); }
    };

    int main()
    {
    A obj;
    obj.test = &A::b;
    (obj.*(obj.test))();
    obj.callTest();
    obj.test2=&A::c;
    obj.test2();
    }
     
  5. Occurrence

    Rekisteröitynyt:
    23.06.2007
    Viestejä:
    839
    Mutta jos se funktiopointteri pitää sijoittaa luokan ulkopuolella olevaan. Jos nyt oikein ymmärsin niin sijoitit sitä vain luokan sisäiseen muuttujaan.

    Jotain voi kyllä olla tuossakin että teet sijoituksen luokan ulkopuolella. Se ei vaan tule kyseeseen koska tuota luokan sisäistä funktiota on tarkoitus käyttää callbackkinä funktiolle millä ei ole mitään tekemistä luokan kanssa. Tämä on vähän kökköä mutta valmiiden kirjastojen käyttö luokan sisällä ei aina ole kaunista.

    Pointteri siis pitää aidosti olla muotoa "void (*test)();" luokan ulkopuolella käytettynä.
     
  6. Photiou

    Rekisteröitynyt:
    23.11.2005
    Viestejä:
    938
    Yrität tunkea neliötä pyöreään reikään:
     
  7. Occurrence

    Rekisteröitynyt:
    23.06.2007
    Viestejä:
    839
    Ei tuon pitäisi olla teknisesti mahdotonta mutta siitä on tehty mahdotonta. Ymmärrän että ei ole tuettuna.

    Miten muutes tehdään tyyppimuunnos tuohon tyyppiin void (*test)() ?
     
    Viimeksi muokattu: 19.10.2021
  8. Photiou

    Rekisteröitynyt:
    23.11.2005
    Viestejä:
    938
    vaikka (decltype(A::test))(&A::b).

    Mutta veren kaivamista nenästä vaikka toimisikin.

    Testasin gcc:llä ja "toimii", mutta käytännössä lukee olion tiedot 'joltain muistialueelta'. Eli segfaultia ja hämäriä arvoja instanssimuuttujille tiedossa.
     
    Viimeksi muokattu: 19.10.2021
  9. Occurrence

    Rekisteröitynyt:
    23.06.2007
    Viestejä:
    839
    Tarkoitin että miten minkä tahansa funktiopointterin typin voi muuntaa muotoon void (*test)() missä siis ei ole mitenkään luokkaa mukana.
    Arduinojen kanssa muistisuojauksilla ei ole väliksi kunhan kutsu itsessään toimii.
     
  10. Photiou

    Rekisteröitynyt:
    23.11.2005
    Viestejä:
    938
    Edellisessä viestissäni on esimerkki miten voit ampua jalkasi irti c++:lla,, funktiotyypit on syystä erilaisia (jäsen vs. normaali funktio).

    Jos toimivaa koodia haluat niin:
    a) käytä normaalia funktiota (ei jäsenfunktio) tai staattista jäsenfunktiota callbackiin
    b) lue aiemmassa viestissä mainittu faq ja rakenna callbackia varten wrapperi joka kutsuu jäsenfunktiota otukselle
     
  11. Occurrence

    Rekisteröitynyt:
    23.06.2007
    Viestejä:
    839
    En vielä luovuta. Taidan kokeilla josko puran luokan sisällä olevan funktion osoitteen tavuiksi muodosta siitä void* tyyppisen functio pointterin ylikirjoittamalla tavu kerrallaan. Pointterin pointterillahan tuo lukeminen ja ylikirjoitus pitäisi onnistua.
    Muistisuojausta kun arduinossa ei ole niin voisi jopa toimia.
     
  12. Photiou

    Rekisteröitynyt:
    23.11.2005
    Viestejä:
    938
    Ei siinä edelleenkään siirry se tieto mille oliolle sitä jäsenfunktiota kutsutaan ... veivasit sitten sitä pointteria sitten muotoon tai toiseen.
     
  13. Occurrence

    Rekisteröitynyt:
    23.06.2007
    Viestejä:
    839
    En tarvitse kuin funktion kutsuosoitteen. Se riittää toisen kirjaston callback-kutsulle mikä ei ole oliotyyppinen.
    Olion functiolla on todellinen kutsuosoite, periaatteessa vaikka olion instanssia ei olisi edes vielä luotu. Olion funktion suoritettava koodi on olemassa aina (paitti jos olion instanssia ei koskaan luoda jolloin on suuri todenäköisyys että kääntäjä optiomoisi sen pois).
     
    Viimeksi muokattu: 21.10.2021
  14. Photiou

    Rekisteröitynyt:
    23.11.2005
    Viestejä:
    938
    Jos ei ole väliä mille instanssille metodia kutsutaan, niin kannattaa tehdä se wrapperi ja kutsua siellä vaikka jollekin vakio instanssille. Eipähän sitten lue/kirjoittele minne sattuu. Olettaen että sulla ei ole pääsyä koodiin, koska muutenhan tossa koko sun hommassa ei ole mitään järkeä.
     

Jaa tämä sivu

Alibi
Anna
Deko
Dome
Erä
Hymy
Kaksplus
Kippari
Kotilääkäri
Kotiliesi
Koululainen
Ruoka.fi
Parnasso
Seura
Suomen Kuvalehti
TM Rakennusmaailma
Tekniikan Maailma
Vauhdin Maailma
Golfpiste
Vene
Nettiauto
Ampparit
Plaza
Muropaketti